Каков ожидаемый результат при переопределении true для false и наоборот?

#include <iostream>
#define true false
#define false true
int main() {
 std::cout << false << true;
}
</iostream>

Почему он выводит "01"?

2 ответа

Как отмечает Джерри Коффин, вы не можете определить макрос с именем, которое является ключевым словом.

Однако мы могли бы рассмотреть другой аналогичный пример с четко определенным поведением и тем же результатом. Рассмотрим:

int TRUE = 1;
int FALSE = 0;
#define TRUE FALSE
#define FALSE TRUE
std::cout << FALSE << TRUE;

Когда вы используете FALSE, он идентифицируется как макрос FALSE и заменяется этим списком замены макросов, который является единственным токеном, TRUE. Эта замена затем повторно сканируется для замены других макросов.

TRUE в замене затем идентифицируется как макрос и заменяется его списком замещения, который является единственным токеном FALSE. Эта замена снова повторно сканируется.

Если мы продолжим повторное сканирование и замену, мы закончим бесконечный цикл, поэтому спецификации предварительной обработки C (и С++) указывают, что замена макроса никогда не повторяется в списке заметок.

Так как замена FALSE в этом финальном списке замещения приведет к рекурсии, остановка макросъемки прекратится, и мы останемся с FALSE, который является именем int со значением 0.


Любая попытка переопределения зарезервированного слова дает поведение undefined.

Изменить:

§2.11/1: "Идентификаторы, указанные в таблице 3, зарезервированы для использования в качестве ключевых слов". Я не буду пытаться воспроизвести всю таблицу 3, но она включает как ложные, так и истинные. Может быть открытым вопрос о том, является ли это абсолютным запретом, хотя, поскольку одно и то же предложение добавляет: "(то есть они безоговорочно рассматриваются как ключевые слова в фазе 7)", что предполагает возможность переопределения ключевых слов в этом так как задействованные макросы будут/расширены до фазы 7.

В этом случае, однако, вы также включили , который вводит другое правило (§17.4.3.1.1): "Единица перевода, которая включает заголовок, не должна содержать макросов, которые определяют объявленные имена или определяется в этом заголовке. Также такая единица перевода не определяет макросы для имен, лексически идентичных ключевым словам."

Формулировка здесь настоятельно указывает на то, что существует намерение, что если единица перевода не содержит никакого заголовка, было бы свободно переопределять ключевое слово, как вы это делали, но с учетом наличия #include нет вопросов, что у вас есть поведение undefined.

Как только у вас будет поведение undefined, больше нечего сказать о "почему", что-то происходит - в этот момент в стандарте очень ясно, что любое поведение допустимо.

licensed under cc by-sa 3.0 with attribution.