当将true重新定义为false,或将false重新定义为true时,预期输出是什么?

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

为什么它输出“01”?

24
真的吗?你写了那段代码?把true定义为false,反之亦然?找一只最近的鞋子,重复用力地打自己的头,直到你弄清楚问题所在。 - Cody Gray
1
我没有写这段代码,我只是想理解它。 - hired777
2
这可能可以通过一个鲜为人知的、通常不起眼(但在某些情况下非常相关)关于宏扩展的事实来解释,但当你开始引用标准时,最好缩短路线并陈述Jerry Coffin已经陈述过的内容。就ISO而言,编译器可能会发动机器人革命,并让机器人用最近的鞋子打作者,以使@CodyGray感到高兴。 - user395760
@hired777 你期望它打印什么,为什么? - Mr Lister
请查看此线程:https://dev59.com/9HE85IYBdhLWcg3wikEu - Karoly Horvath
6
@Griwes: 实际上,楼主有些道理:在表面层次上(和深层宗教偏见的情况下)似乎是个“什么鬼问题”,但这是#define递归最简单的示例(除了他使用关键词作为宏,从而引起未定义行为,但可以轻松解决)。通过我的经验,大多数程序员甚至不知道这种情况存在。如果需要尝试解决它,他们只会“逃避”。所以当错误地进行递归时,他们无法识别问题。 - Emilio Garavaglia
2个回答

13

正如Jerry Coffin所指出的那样,您不能定义一个名称为关键字的宏。

但是,我们可以考虑另一个类似的例子,具有明确定义的行为和相同的结果。请看:

int TRUE = 1;
int FALSE = 0;

#define TRUE FALSE
#define FALSE TRUE

std::cout << FALSE << TRUE;
当你使用FALSE时,它被识别为宏FALSE并替换为该宏的替换列表,即单个令牌TRUE。然后重新扫描此替换结果以进行进一步的宏替换。TRUE在替换中被识别为一个宏,并被其替换列表所取代,即单个令牌FALSE。然后再次重新扫描此替换结果。如果继续这样的替换和扫描,我们将陷入无限循环,因此C(和C ++)预处理规范说明宏替换永远不会在替换列表内递归。由于在最终的替换列表中替换FALSE将导致递归,因此宏替换停止,我们最终得到的是FALSE,它是一个值为0的int类型名称。

好的解释!但只有一个问题,你是在给他提供像上面那样写更多代码的想法吗? - noMAD
5
@noMAD:通常情况下,我们不应该编写这样的代码,但这并不意味着我们不应该解释为什么这段代码能够正常运行。即使是语言中“无人问津”的“荒唐角落”,了解编程语言的工作原理也很重要。值得一提的是,我曾经编写过完全像这样的代码,用于测试我一段时间内正在开发的 C 预处理器实现(承认有些奇怪)。 - James McNellis

11

试图重新定义保留字会导致未定义的行为。

编辑:

§2.11 / 1:“表3中显示的标识符被保留用于关键字。”我不会尝试再现整个表3,但它包括false和true。这可能存在一些问题,是否绝对禁止这样做,因为同一句话补充说:“(也就是说,在第7阶段它们被无条件地视为关键字)”,这表明可以通过这种方式重新定义关键字,因为所涉及的宏将在第7阶段之前/时展开。

但是,在这种情况下,您还包括了<iostream>,这引入了另一个规则(§17.4.3.1.1):“包含头文件的翻译单元不得包含定义在该头文件中声明或定义的名称的任何宏。此类翻译单元也不得为词法上与关键字相同的名称定义宏。“

这里的措辞强烈暗示,如果翻译单元不包括任何头文件,那么就可以自由地重新定义关键字,就像您所做的那样,但是鉴于存在#include <iostream>, 没有疑问,您会有未定义的行为。

一旦您有了未定义的行为,关于“为什么”发生任何事情就没有更多可说的了 - 在那一点上,标准非常明确,任何行为都是允许的。


1
为什么不直接去查看 ISO,而是要求“链接”呢?无论如何,“链接到 ISO”的链接都指向文档,因此它不会给你任何新东西。 - Griwes
1
我们是否像ISO标准的人机界面或其人性化指数? - Griwes
2
@Griwes 鉴于有大量的“语言律师”问题,这些问题的答案都包含了标准中完美的属性引用,我们必须这样做。 - user395760
哦,难道这就是那么简单吗? :-) 给出被 @yi_H 链接的问题的被接受答案的人可能对那个问题想太多了,完全错过了第2.11/1节中明显的答案。 - James McNellis
1
@JerryCoffin 这不是一个答案,而是一条评论。请扩展它。 - casperOne
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接