有人可以向我解释为什么这段代码打印减少的金额?由于(4 <= 3)是假的,不应该继续打印“Hi”?
int main()
{
int amount = 4;
if((amount%5) <= (--amount))
printf("%d", amount);
else
printf("Hi");
}
答案 0 :(得分:3)
原来这个代码是 undefined 。你已经得到了表达式
(amount%5) <= (--amount)
但关键问题是amount%5
部分在被amount
部分递减之后是否使用旧值--amount
或新值?答案是:我们不知道。没有办法说出来。 C语言中没有规则告诉我们。
您可能认为代码必须从左到右进行评估,amount%5
部分必须首先发生,而--amount
部分才有机会发生。但这不是它的工作方式。由于它未定义,任何事情都可能发生。
如果它或多或少地从左到右评估,那么我们有
if(amount%5 <= --amount)
评估为
if(4%5 <= --amount)
评估为
if(4 <= --amount)
评估为
if(4 <= 3)
这是假的,所以你可能希望它打印&#34;嗨&#34;。 但是,如果它或多或少地从右到左进行评估,那就
if(amount%5 <= 3)
评估为
if(3%5 <= 3)
评估为
if(3 <= 3)
这是真的。
(你会注意到我已经删除了一些额外的括号,因为他们没有做任何事情。)
我赶紧补充说,这些不是唯一的两种可能性。规则说,一旦表达式未定义,字面上任何都可能发生 - 行为不一定是我们可能考虑的任何事情&#34;合理的&#34;一点都不。
那为什么不定义?在这种情况下,它是因为你有一个变量 - amount
- 在表达式中出现两次,其中一个外观是修改(--amount
部分),其中另一个使用变量的值。 C标准明确告诉我们,在这种情况下(a)我们无法判断amount
的使用是使用旧的还是修改的值,而且(b)表达式中的这个缺陷 - 这种同时修改和使用 - 使整个表达式(实际上它所在的整个程序)未定义。
那么你如何解决它?答案很简单,这是一个古老笑话的妙语:不要这样做。不要在单个变量(或其他对象)被修改和使用的情况下编写表达式。写--amount
没关系,只是不要在表达式中使用变量amount
的其他地方。
这样的问题经常出现。在Why are these constructs (using ++) undefined behavior in C?问题下收集了其他已经重定向的规范SO答案。关于未定义表达式的规则,我可以说更多,但你可以在那个问题上找到这些细节。