[英]The use of condition
先生,请您告诉我,为什么“ C ”中的以下条件为false
?
main()
{
int i=1;
if(i<=i++)
printf("false");
else
printf("true");
}
它不是假的,当它为true时,您只打印false
。
比较运算符<=
没有指定先评估哪一方,即i
或i++
,并且比较函数的左侧操作数末尾没有序列点(请参见http://www.gnu .org / software / gnu-c-manual / gnu-c-manual.html#Sequence-Points )。
如果首先评估左侧,则会得到:
if (1 <= 1)
如果首先评估右侧,则会得到:
if (2 <= 1)
这突出了问题所在,但甚至比那更糟。
您编写的代码具有未定义的行为,即“未定义”。 在这种情况下,编译器可以执行任何操作 ,但仍符合标准。
例如,这些编译器(带有-O3
)遵循else分支:
这些编译器(带有-O3
)遵循true
分支:
g++-4.7 (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
其他编译器可能会做一些完全不同的事情。
这是未指定行为的组合,只是简单的未定义行为 。 因此,您无法预测此代码的结果,因此无法依赖结果。 未指定,因为在此行中:
if(i<=i++)
我们不知道将首先评估i
还是i++
。 C99标准草案第6.5
节第3款规定 :
语法表示操作符和操作数的分组。74)除非稍后指定(对于函数调用(),&&,||,?:和逗号运算符), 子表达式的求值顺序和哪种副作用都未指定。
上面提到的那行也是未定义的行为,因为在序列点之间,我们只允许修改一次变量,如果我们对其进行修改,则只能读取前一个值以确定要设置的新值。 在这种情况下,我们正在读取先验值以确定i
和i++
。 从标准草案第6.5
节第2段开始 :
在上一个序列点与下一个序列点之间,对象的存储值最多只能通过对表达式的求值来修改 。 此外, 先验值应只读以确定要存储的值。
为了理解您的代码在做什么,我将重新编写代码,只是非常明确:
main()
{
int i=1;
if(i<=i) {
i++;
printf("false");
} else {
i++:
printf("true");
}
}
i++
表示在比较之后将i++
递增。 在i的两个分支中,如果i正在递增,则等效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.