C++ 当将true重新定义为false,反之亦然时,预期的输出是什么? #包括 #定义真假 #定义假真 int main(){ std::cout

C++ 当将true重新定义为false,反之亦然时,预期的输出是什么? #包括 #定义真假 #定义假真 int main(){ std::cout,c++,language-lawyer,C++,Language Lawyer,任何重新定义保留字的尝试都会导致未定义的行为 编辑: §2.11/1:“表3中所示的标识符保留用作关键字。”我不会尝试复制表3中的所有内容,但其中包括false和true。尽管如此,这是否是一项绝对禁止还是一个疑问,因为同一句话补充道:“(也就是说,它们在第7阶段被无条件地视为关键字)”,这表明可以通过这种方式重新定义关键字,因为所涉及的宏将在第7阶段之前展开 然而,在本例中,您还包括了,这带来了另一条规则(§17.4.3.1.1):“包含标题的翻译单元不得包含任何定义在该标题中声明或定义的名称

任何重新定义保留字的尝试都会导致未定义的行为

编辑:

§2.11/1:“表3中所示的标识符保留用作关键字。”我不会尝试复制表3中的所有内容,但其中包括false和true。尽管如此,这是否是一项绝对禁止还是一个疑问,因为同一句话补充道:“(也就是说,它们在第7阶段被无条件地视为关键字)”,这表明可以通过这种方式重新定义关键字,因为所涉及的宏将在第7阶段之前展开

然而,在本例中,您还包括了
,这带来了另一条规则(§17.4.3.1.1):“包含标题的翻译单元不得包含任何定义在该标题中声明或定义的名称的宏。此类翻译单元也不得为与关键字词汇相同的名称定义宏。”

这里的措辞强烈表明,如果翻译单元不包含任何标题,它可以像您所做的那样自由地重新定义关键字,但考虑到
#include
,毫无疑问您有未定义的行为


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

正如Jerry Coffin所指出的,您不能用关键字的名称定义宏

然而,我们可以考虑另一个类似的例子,具有明确的行为和相同的结果。

#include <iostream>
#define true false
#define false true
int main() {
    std::cout << false << true;
}
int TRUE=1;
int假=0;
#定义真假
#定义假真

std::真的吗?你写的代码?定义
true
false
,反之亦然?找到最近的鞋子,用它反复捶自己的头,直到你发现问题所在。我没有写这段代码(=我只是想理解它可能可以用一个鲜为人知的、通常是晦涩难懂的词来解释(但在某些情况下非常相关)事实与宏扩展有关,但当你开始引用标准时,你可能会短路并陈述Jerry Coffin已经说过的内容。就ISO而言,编译器可能会启动一场机器人革命,让机器人用最接近的鞋子击败作者,让@CodyGray感到高兴。@hired777你希望它打印什么d为什么?@Griwes:实际上OP有一些要点:在表面层面(以及深层次的宗教偏见)这似乎是WTF的问题,但这是最简单的例子(除了他使用宏的关键字,因此导致UB,但很容易用其他符号解决)关于#定义递归。根据经验,我知道大多数程序员甚至都没有意识到。如果需要尝试解决它,他们只是“逃逸”了。因此,当错误地重新计算时,他们无法识别问题。你为什么不去看看ISO,而不是要求“链接”到它?无论如何,“链接到ISO”链接到文档,所以它不会给你任何新的东西。我看穿了它,但我找不到解释我们看起来像ISO标准的人机界面还是它的人文索引?@Griwes考虑到
语言律师
问题的数量,我们有完全引用标准属性的答案。@JerryCoffin这不是答案但是一个评论。请扩展它。很好的解释!但是只有一个问题,你是否给了他写更多类似于上面的代码的想法???@noMAD:不,人们通常不应该写这样的代码,但这并不意味着我们不应该解释为什么这个代码会这样工作。理解你的编程语言是很重要的,ev在“无人使用”的语言的“愚蠢”角落里,我写了与此完全相同的代码,在一个C预处理器实现的单元测试中,我工作了一段时间(无可否认,我有奇怪的爱好)。
int TRUE = 1;
int FALSE = 0;

#define TRUE FALSE
#define FALSE TRUE

std::cout << FALSE << TRUE;