将 true 重新定义为 false 时的期望输出是多少,反之亦然
What is the expected output when redefining true to false and vice versa?
#include <iostream>
#define true false
#define false true
int main() {
std::cout << false << true;
}
为什么输出"01"?
正如 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
的名称。
任何重新定义保留字的尝试都会产生未定义的行为。
编辑:
§2.11/1:"表 3 中显示的标识符保留用作关键字。我不会尝试重现表 3 的所有内容,但它包括假和真。不过,这是否是绝对禁止可能会受到一些质疑,因为同一句话补充说:"(也就是说,它们在第 7 阶段被无条件地视为关键字(",这表明可以通过这种方式重新定义关键字,因为所涉及的宏将在阶段 7 之前扩展。
但是,在本例中,您还包含了 <iostream>
,这带来了另一个规则 (§17.4.3.1.1(:"包含标头的翻译单元不得包含定义在该标头中声明或定义的名称的任何宏。这样的翻译单位也不得为词法上与关键字相同的名称定义宏。
这里的措辞强烈表明,如果翻译单元不包含任何标题,则可以像您所做的那样自由地重新定义关键字,但考虑到#include <iostream>
的存在,毫无疑问您有未定义的行为。
一旦你有了未定义的行为,就真的没有更多关于"为什么"任何事情发生的说法了——在这一点上,标准非常明确,任何行为都是允许的。
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 期望文本输出而不是数字
- 这是循环击中两个输出,而不仅仅是我期望的输出
- 我在 main 下的输出不是我所期望的
- 将 true 重新定义为 false 时的期望输出是多少,反之亦然
- 期望输出带有指针和引用混合的代码
- 程序没有给出期望的输出.FIFO的错误实现