C 我不知道';我不理解这段代码的输出

C 我不知道';我不理解这段代码的输出,c,post-increment,pre-increment,C,Post Increment,Pre Increment,我正在学C,老师给了我们一些家庭作业。我们必须确定一些代码的输出。我不明白为什么y=4 代码如下 int main() { int w = 3, y = 3; printf("w = %i\n", --w + w--); printf("y = %i\n\n", y = w + y++); return 0; } 由于在两个序列点之间修改变量值两次,因此该行为未定义 您应该阅读更多关于序列点的信息。这是标准对其的说明: 在被称为序列点的执行序列中的某些指定点

我正在学C,老师给了我们一些家庭作业。我们必须确定一些代码的输出。我不明白为什么
y=4

代码如下

int main() {

    int w = 3, y = 3;
    printf("w = %i\n", --w + w--);
    printf("y = %i\n\n", y = w + y++);

    return 0;
}

由于在两个序列点之间修改变量值两次,因此该行为未定义

您应该阅读更多关于序列点的信息。这是标准对其的说明:

在被称为序列点的执行序列中的某些指定点,先前评估的所有副作用应完整,且后续评估的副作用不得发生

未定义的行为 此代码(至少)在以下两部分中存在未定义的行为(如中所述):

--w + w--

y = w + y++
这意味着你得到的结果不是可移植的,也不是有保证的

说谎代码 除了未定义的行为之外,输出实际上由您决定<代码>printf(“w=%i\n”,--w+w--)看起来像是在打印
w
的值(因为它打印
w=…
),但它不是在打印
w
的值,而是在打印
--w+w--
的值(这是未定义的,所以它实际上是在打印编译器编译的
--w+w--
的值)

那么
w
的值是多少呢? 编译器为
--w+w--
生成的代码具有使
w
的值为
1
的副作用,因为它最初是
3
,并且
--w
w--
递减
w
。但是,
--w+w--
(在编译器生成的代码中,基于您得到的输出,
4
。这是什么原因?首先可以计算
--w
,它将
w
3
递减到
2
,并返回
w
的新值,即
2
。然后可以计算
w-->
已计算,它将
w
2
递减到
1
,但返回
w
的原始值,即
2
2
2
之和当然是
4

因此,
--w+w--
的值是
4
,而
w
的新值是
1

那么
y
会发生什么呢?
w
的新值是
1
,因此执行时(回想一下
y
的值是
3
):


y++
的副作用是
y
是递增的(但不确定是在赋值之前还是之后发生),但表达式的值是
y
,在本例中是
3
。因此,您要添加
w
,其值是
1
,以及
y++
,其值是
3
。然后将
4
赋值给
y
,赋值的值是
4
,因此您得到了
4
作为输出。在
y=w+y++
中仍然存在未定义的行为,因为不清楚
y
的增量应该在什么时候发生:在分配之前还是之后?

让我以一条重要的公共服务公告作为序言:

当你的编译器给你一个警告,任何警告,你最好注意它。你问题中的代码示例会导致未定义的行为——换句话说,C标准不能保证每个编译器都会给出相同的结果,因为你的代码。这总是一件坏事

有了这一点,下面是对正在发生的事情的解释

我稍微修改了您的代码,以查看w的中间值:

#include <stdio.h>

int main(void) {

    int w = 3, y = 3;
    printf("w = %i\n", --w + w--);
    printf("w is actually %d\n", w);
    printf("y = %i\n\n", y = w + y++);

    return 0;
}
输出是

w = 4
w is actually 1
y = 4
发生了什么?因为编译器从左到右解析语句,所以

--w + w--
似乎会导致以下步骤(对于我的编译器):

结果是求和为
2+2
,第一行打印
4
,但求和后
w
递减为
1
。但是,您不能依赖于此行为-这就是编译器抛出警告的原因。正如Eric Postdischil指出的,可能存在执行顺序可能错误的情况与众不同。“不要这样做”是底线——你在追求未定义的行为

请注意,程序打印的
w等于4这一事实并不意味着在任何时候都是正确的。正如您所看到的,当您实际打印
w
时,它是1

假设编译器按照上述顺序执行这些语句,我们转到下一行:

y = w + y++
我们从
w=1
y=3
开始。这两者的总和是
4
,这是表达式的值

y = w + y++
这就是印刷的内容(4)


作为一个副作用,y是递增的。不管怎样,y的值在最后都是4。如果你改变代码,从
w=5
开始,你的结果是
y=6
。换句话说,
y++
的效果被
y=
作业覆盖。

你的老师假设了一个特定的评估顺序语言不保证的不一致性

假设严格的从左到右评估,并假设立即应用副作用,然后给定
w
y
的起始值,会发生以下情况:

  • --w
    计算为
    w-1
    (2),作为副作用,w
  • 递减;
    w
    现在为2
  • w--
    的计算结果为
    w
    (2),作为副作用,
    w
    w
    现在为1
  • 作为1和2的结果,
    --w+w--
    计算结果为4
  • y++
    的计算结果为
    y
    ,作为副作用,
    y
    y
    现在为4
  • 作为4的结果,
    w+y
    
    --w  : decrement w, it is now 2
    w--  : use the value of '2', but decrement w when you are done
    
    y = w + y++
    
    y = w + y++
    
    x++ + x++   
    a[i++] = i
    y = y++
    
    foo(y++, y++);