gcc中的C副作用(前缀/后缀运算符和优先级)

时间:2013-05-15 10:09:03

标签: c gcc

我有小C代码:

#include<stdio.h>
int main() 
{
    int  z[]= {1,2,3,4,5,6};
    int i = 2, j;
    printf("i=%d  \n",i); 

    z[i] = i++;

    for (j=0;j < 6;j++ )
       printf ("%d ", z[j]);

    printf("\ni=%d \n",i); 
}

输出:

i=2  
1 2 2 4 5 6 
i=3

评估表达式的优先顺序是   首先,评估z [i]。因为我在这里2,它变成了z [2]。   接下来,评估i ++,即得到2,i变为3。   最后,执行=,并将2(即从i ++产生的值)放到z [2]

这解释了上述输出,即1 2 2 4 5 6

但是,如果我们将上述代码从i ++更改为++ i,即

#include<stdio.h>
int main() 
{
    int  z[]= {1,2,3,4,5,6};
    int i = 2, j;
    printf("i=%d  \n",i); 

    z[i] = ++i;

    for (j=0;j < 6;j++ )
       printf ("%d ", z[j]);

    printf("\ni=%d \n",i); 
}

然后输出奇怪地不同,即:

i=2  
1 2 3 3 5 6 
i=3

如果我们按照上述优先顺序(C规范说[index]早于++绑定)那么 输出应该是1 2 3 4 5 6。

我只是想知道为什么上面的优先顺序没有解释这个?

我的编译器是ubuntu 11.04上的gcc 4.5.2

谢谢和问候, 卡皮尔

5 个答案:

答案 0 :(得分:3)

z[i] = ++i;导致未定义的行为:

6.5表达
...
2如果相对于同一标量对象的不同副作用或使用相同标量值的值计算,标量对象的副作用未被排序 对象,行为未定义。如果有多个允许的排序  表达式的子表达式,如果这样一个未经测序的一方,则行为是不确定的   效果发生在任何排序中。 84)
84)此段落呈现未定义的语句表达式,例如

    i = ++i + 1;
    a[i++] = i;
同时允许

    i = i + 1;
    a[i] = i;

请注意,优先级仅控制运算符和操作数的分组;它控制评估顺序。

++++i运算符的副作用相对于[]中的z[i]运算符未序列;编译器不需要以任何特定顺序评估这两个表达式。另请注意,在评估表达式后,不需要立即应用++i副作用;它只需要在下一个序列点之前应用。

答案 1 :(得分:2)

这不是错误,请查看GCC non-bug section。这种测试会导致不可预测的结果并且他们知道。

  

在两个序列点[...]之间修改两次值会导致未定义的行为。

答案 2 :(得分:2)

 z[i] = ++i;

是未定义的行为

引用C section of cppreference.com

  

1)如果相对于标量对象的副作用未被排序   对同一个标量对象的另一个副作用是行为   未定义。

     

i = ++ i + i ++; //未定义的行为

答案 3 :(得分:0)

z [i] = ++ i;

调用未定义的行为。

答案 4 :(得分:0)

http://www.faqs.org/faqs/C-faq/faq/问题3.1至3.9。这些都是与您的问题类似的所有问题的答案。

但简而言之,两个序列点之间的评估顺序(这些由C标准--C99附录C明确定义)是未定义的行为。

  

在两个序列点之间,对象被多次修改,或者被修改并且读取先前值而不是确定要存储的值