代码在C中给出了错误的结果

时间:2018-05-05 01:01:02

标签: c

有人可以向我解释为什么这段代码打印减少的金额?由于(4 <= 3)是假的,不应该继续打印“Hi”?

int main()
{
    int amount = 4;

    if((amount%5) <= (--amount))
        printf("%d", amount);
    else
        printf("Hi");
}

1 个答案:

答案 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答案。关于未定义表达式的规则,我可以说更多,但你可以在那个问题上找到这些细节。