我是一名业余C程序员,我在一本书中遇到过这个问题,有人可以给我一个有效的解释.我对这个^符号在C程序中的作用感到困惑.
#includeint main(void) { int a; printf("%d", (3^6) + (a^a)); return 0; }
ouah.. 10
int a; printf("%d",(3^6)+(a^a));
(3^6)+(a^a)
expresion 的评估调用未定义的行为,因为a
未初始化并具有不确定的值.
(C11,6.3.2.1p2)"如果左值指定了一个自动存储持续时间的对象,该对象可以用寄存器存储类声明(从未使用过它的地址),并且该对象未初始化(未使用初始化程序声明,并且没有在使用之前已对其进行了赋值),行为未定义."
@datenwolf它很重要.C表示它会调用未定义的行为. (10认同)
@datenwolf"你不能说"哦,这样做会调用UB,因此我可以不再在这里思考"" - 哦,是的,我们可以.这恰好是UB的重点.此外,您混淆了未定义的**行为**和未指定的**值.**两者不等同. (9认同)
@datenwold欢迎来到未定义行为的领域 (7认同)
@datenwolf UB允许,例如,`a`在第一次读取时看起来是1,然后它的值突然变为0.然后`a ^ a`将**不**是0. UB是UB,并且有对于具有未定义行为的程序的输出没有任何影响/约束. (6认同)
@datenwolf标准不涉及在生成的程序集中读取或其他任何内容.它关注抽象机器的操作.当然,由于"as-if"规则,允许编译器消除"a ^ a"(如果定义了程序的行为),但是C抽象机仍然完全按照源代码,**是的,`a ^ a`**总是**导致两次读取; 也许不是在物理上或在实际的汇编程度,但理论上.而这本身就是未定义的行为.没有人关心`a ^ a`是否会被优化为常数0. (6认同)
@datenwold你在6.3.2.1p2中读过哪里需要`volatile`限定符?未定义的行为"a ^ a"可以评估为"42",或者程序可能崩溃等. (5认同)
@datenwolf但是,由于程序有UB(因为它读取了一个未初始化的变量),它可以做任何事情; UB并不意味着"这一个值将是不确定的,但每个其他陈述必须表现得正常".UB意味着"唯一的规则就是没有规则".因此**可以从这样的程序中预期任何**行为/输出.它不符合要求,因此它不需要遵守标准对**正确,符合**程序执行的规则. (5认同)
@datenwolf是的,你可以,这就是UB的定义.您可能正在考虑编译器需要记录的"未指定的行为"(并且它不可移植,并且因为我们不知道OP的编译器,所以它仍然未定义给我们). (5认同)
@datenwolf托马斯正在谈论**未指明的**行为,而不是**未定义的**行为. (5认同)
@datenwolf这是隐含的.C99,3.4.3.1中UB的定义是"使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对其施加任何要求".因此,如果程序具有UB,则不要求变量保留其值. (5认同)
@datenwolf是的,**大多数**实现确实将它评估为零.但任何人都可以依赖它吗?不会.您的代码只需更改编译器标志就可以停止工作,或者因为今天正在下雨. (5认同)
@datenwolf就在这里:"*行为未定义*" (4认同)
@datenwolf:总会有人会开始无休止地讨论如何通过某种黑魔法来改变一些未定义的行为.它相当于一个科学研究计划,变成了看不见的独角兽的颜色 - 但在某些时候你只需要坚持它是不可见的事实. (3认同)
@datenwolf,你假设表达式'a`读取变量的值.但是标准只表示它在初始化变量时读取值.也许表达式"a"在屏幕上打印"Hello World"并在不是时退出,谁知道呢? (2认同)
haccks.. 6
我对这个^符号在C程序中的作用感到困惑.
^
是一个逻辑XOR运算符(不要与幂运算符混淆,遗憾的是在C中不可用).
在C语言中输出表达式(3 ^ 6)+(a ^ a)?
程序的输出是垃圾值,因为程序的行为是未定义的.为什么?因为a
没有初始化.
在以下情况下,行为未定义:
...
- 指定可以使用寄存器存储类声明的自动存储持续时间的对象的左值在需要指定对象的值的上下文中使用,但对象是未初始化(6.3.2.1).1
1.重点是我的.
我对这个^符号在C程序中的作用感到困惑.
^
是一个逻辑XOR运算符(不要与幂运算符混淆,遗憾的是在C中不可用).
在C语言中输出表达式(3 ^ 6)+(a ^ a)?
程序的输出是垃圾值,因为程序的行为是未定义的.为什么?因为a
没有初始化.
在以下情况下,行为未定义:
...
- 指定可以使用寄存器存储类声明的自动存储持续时间的对象的左值在需要指定对象的值的上下文中使用,但对象是未初始化(6.3.2.1).1
1.重点是我的.
int a; printf("%d",(3^6)+(a^a));
(3^6)+(a^a)
expresion 的评估调用未定义的行为,因为a
未初始化并具有不确定的值.
(C11,6.3.2.1p2)"如果左值指定了一个自动存储持续时间的对象,该对象可以用寄存器存储类声明(从未使用过它的地址),并且该对象未初始化(未使用初始化程序声明,并且没有在使用之前已对其进行了赋值),行为未定义."
程序的输出将导致未定义的行为,因为a
未初始化,因此输出将导致任何垃圾值.