C 为什么if语句中未定义的behavoir为true?
在这个程序中有一个未定义的行为。输出总是C 为什么if语句中未定义的behavoir为true?,c,undefined-behavior,C,Undefined Behavior,在这个程序中有一个未定义的行为。输出总是true。我试过几个编译器。有人能解释一下为什么它总是true吗?是的,代码将始终返回true,因为任何条件语句中的任何非零值都是true(上面的C-99)或1(C-99) 在if条件中,2首先分配给y,然后2与2按位&'。 i、 e.0010和0010结果将返回0010 现在你有了: if (y & (y = 2)) printf("true %d\n"); 您试图在序列点之间多次修改y的值。对于如何处理这种行为,没有一个标准的方法。因
true
。我试过几个编译器。有人能解释一下为什么它总是true
吗?是的,代码将始终返回true
,因为任何条件语句中的任何非零值都是true
(上面的C-99)或1
(C-99)
在if条件中,2首先分配给y,然后2与2按位&'。
i、 e.0010和0010结果将返回0010
现在你有了:
if (y & (y = 2))
printf("true %d\n");
您试图在序列点之间多次修改y的值。对于如何处理这种行为,没有一个标准的方法。因此:
if(2) //Any non-zero value is true
printf("true %d\n");
瓦尔特因为观察到的行为没有定义。您正在使用的编译器(仅通过观察)似乎正在执行以下操作:
y=2
y
(2和2)
,这是正确的。问题是,1-2,然后3的顺序不是标准定义的。也可能是这样的:
y
y=2
(1和2)
,即false
或者完全是别的什么东西。并不是所有的编译器都会做第一件事,你不能假设,因为你使用的编译器都会做第一件事。你也不能假设,因为他们这样做了,而且你观察到了这种行为,所以它就被定义了;事实并非如此编译器不定义行为;标准是这样的,编译器有义务遵守。
注:这个定义时代有一个漏洞,但它不是规范,甚至标准对它的定义也很松散。你会发现标准中的一些地方,比如“实现定义”。在这种情况下,标准会合理清晰地指出这些分歧的地方。在这种情况下,您应该咨询您的实现以获得关于预期行为的最终结论,并且在这样做的过程中,准备接受一个简单的事实,即这种行为只能在实现的范围内被依赖。这(你的样品)不是这样的漏洞例外
根据我的观察,我的Clang3.5装备似乎运行第二个序列,而不是第一个序列,我可以按照你的方式假设我尝试过的“所有”编译器(其中一个)都是这样运行的,因此它被定义为这样。我这样做是错误的,正如你所设想的那样
未定义的行为就是这样;未定义。您使用的是按位and&,使用&&表示普通的“and”运算符,如果要检查其是否为2,则y==2。此外,由于您没有传递printf任何内容,因此该代码将无法工作。非常确定的是,(0x01&0x02)为false,但他尝试的所有编译器似乎都会首先计算括号赋值,从而导致(0x02&0x02),这是真的。正如下面的答案似乎得出的结论,我很确定这项任务不是偶然的。(在有人问之前,我没有投任何人的反对票)@PankajMahato在clang 3.5-O3上编译这个,我收到的是假的,所以可能会改变一下你的测试平台。另外,她也很聪明,给了我这个,我猜你已经知道了:
警告:未排序的修改和访问“y”[-Wunsequenced]
真的没有“为什么”这个问题“在这儿。未定义的行为是未定义的;无法保证它会返回真值。正如提问者所说,行为是未定义的。对两个操作数的求值不存在排序。如果您花时间阅读注释,您会发现它并非总是正确的。即使是这样,这也绝对不会影响行为是否未定义。在LLVM版本5编译器上,get false带有警告。警告:未排序的修改和对“y”@SaurabhSharma的访问:从“在我使用多个编译器测试的每个特定实例中,这都是正确的”推断“这一直是正确的”是无效的。得出“始终如此”(其中“始终”是“每个标准C实现”)结论的唯一方法是从C标准中为C指定的规则中推断出来。标准C的规则很明确:如果您都使用一个对象(y
),并分别修改它(y=2
)在一个表达式中,如果没有对其求值进行排序,则该行为是未定义的。您的第二段简要介绍了所讨论的未定义行为。您假设了该序列,而他尝试执行的编译器似乎就是这样。但是,在您注意到的位置上没有定义的序列点,因此是这样的UB.这个答案中的其他所有内容都解释了为什么结果是真的。这很容易是目前为止最好的答案,如果这个答案只是说“因为你正在使用的编译器似乎可以做到这一点:废话,但它们不是必需的,有些则不是”我会很快对此进行投票。我不想再拖下去了,但可能值得注意的是,编译器可能会检测到表达式(y&(y=2))
未定义(因此既不是真的也不是假的),并优化整个过程。该程序可能根本不会打印任何内容。@StephenCanon这是一个完全公平的观点,值得进行评论投票。或者它可能会决定所有UB评估在我的小“I-get-to-define-what-UB-is-universe”中都是错误的。很好的一点。UB,你是一个残忍无情的婊子。
if (y & (y = 2))
printf("true %d\n");
if(2) //Any non-zero value is true
printf("true %d\n");
i = i++; // gives undefined behavior also