此程序的输出。感到困惑吗? [重复]

问题描述 投票:-3回答:5

所以我被这个问题困扰。

int i=5,a;
a=++i + i++ + ++i + i++ - --i;
printf("%d",a);

根据我的说法,“ a”应为20。a = 6 + 6 + 8-8但是,在执行时,我发现答案是18。我在做什么错?逐步说明会很有帮助。

c increment post-increment pre-increment
5个回答
3
投票

这是未定义的行为。变量不能在序列点之间多次更改。您的程序可以输出任何内容。任何其他说明的答案都是错误的。


3
投票

我已经在http://blog.susam.in/2010/05/sequence-points.html的博客文章中详细介绍了此内容>

我将在此处发布一些摘录。

在C编程论坛中会不时问一个特定类型的问题。这些问题有两件事会激怒论坛中经验丰富的程序员。首先,这种类型的问题非常普遍,以至于许多人甚至都不想回答这些问题,即使这意味着将链接发布到已回答类似问题的另一个主题上。其次,更重要的是,即使有人试图为问题提供正确的答案,也有许多其他人忽略了该问题,并用错误的答案填补了话题。

问题通常涉及找到这样的代码输出。

#include <stdio.h>

int main()
{
    int i = 5;
    printf("%d %d %d\n", i, i--, ++i);
    return 0;
}

使用gcc编译时输出为5 6 5,而使用Microsoft Visual Studio附带的Microsoft C / C ++编译器编译时输出为6 6 6。

此类C程序的行为未定义。在语句printf(“%d%d%d \ n”,i,i--,++ i);和a == a ++ + a ++ ;,分号是唯一的序列点。 C保证给定表达式的所有副作用都由程序中的下一个序列点完成。如果在下一个序列点之前发生了两个或两个以上具有相互影响的副作用的操作,则该行为是不确定的。当使用不同的编译器进行编译时,此类代码的行为可能会有所不同。

在引用ISO / IEC标准的相关部分之前,我先引用K&R的内容。在本书的第2.12节(评估的先后顺序)中,作者写道,

C, like most languages, does not specify the order in which the

对操作员的操作数进行评估。 (例外是&&,||,?:,和','。)例如,在类似[]的语句中

x = f() + g();

f may be evaluated before g or vice versa; thus if either f or g

更改另一个变量所依赖的变量,x可以取决于评估顺序。中间结果可以临时存储变量以确保特定的顺序。

他们在本节中提供了另一个示例。

One unhappy situation is typified by the statement

a[i] = i++;

The question is whether the subscript is the old value of i or the

新。编译器可以用不同的方式解释这一点,并生成不同的答案取决于他们的解释。

如果要了解更多信息,请下载ISO / IEC 9899 C标准,并转到第438页的附件C –顺序点。它列出了所有序列点。 ;是其中之一。 +和++运算符不是序列点。

接下来,请阅读第5.1.2.3节(程序执行)的第2点。

Accessing a volatile object, modifying an object, modifying a

文件,或调用执行任何这些操作的函数,全部副作用,11)是执行状态的变化环境。评价表达可能会产生副作用。在执行序列中的某些指定点称为序列要点,以前评估的所有副作用应完整且后续评估不应有任何副作用。 (一种序列点的摘要在附件C中给出。)

在C语言的标准中,它明确表示只要遵循优先级规则,编译器就可以以任何方式自由地重新排列表达式。这意味着如果您具有以下表达式:

x = foo() + bar() + baz()

这三个函数可以按任何顺序调用,并且是合法的。

在较旧的C语言标准中,它甚至表示如果愿意,编译器可以忽略括号:

x = (foo() + bar()) + baz()

强制确定评估顺序的唯一肯定方法是使用临时变量:

temp0 = foo();
temp1 = bar();
x = temp0 + temp1 + baz();

您要分配给a的表达式表现出未定义的行为,特别是递增/递减操作应用于其操作数的顺序。

取决于编译器执行所有操作的顺序。由于它取决于编译器实现,因此没有“正确”的答案。

例如严格从左向右走:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     first   second  third  fourth  fifth
a = (6) + (6) + (8) + (8) - (7) = 21;

向右->向左:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     fifth   fourth third   second    first
a =  6 + 5 + 5 + 4 - 4 = 16;

1
投票

在C语言的标准中,它明确表示只要遵循优先级规则,编译器就可以以任何方式自由地重新排列表达式。这意味着如果您具有以下表达式:


0
投票

您要分配给a的表达式表现出未定义的行为,特别是递增/递减操作应用于其操作数的顺序。


0
投票

取决于编译器执行所有操作的顺序。由于它取决于编译器实现,因此没有“正确”的答案。

© www.soinside.com 2019 - 2024. All rights reserved.