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

C gcc中的副作用(前缀/后缀运算符和优先级),c,gcc,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); } 计算表达式的优先顺序为 首先,计算z[i]。当

我有小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); 
}
计算表达式的优先顺序为 首先,计算z[i]。当我在这里是2时,它变成z[2]。 接下来,对i++进行评估,即2被产生,i变为3。 最后,执行=并将2(即从i++生成的值)放入z[2]

这解释了上述输出,即1 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); 
}
如果我们按照上面的优先级(C规范所说的[index]的绑定早于++),那么 输出应该是123456

我只想知道,为什么上述优先次序不能解释这一点

我的编译器是ubuntu 11.04上的GCC4.5.2

感谢和问候, Kapil

z[i]=++i


调用未定义的行为

这不是一个bug,请查看。这种测试会导致不可预测的结果,他们知道这一点

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


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

6.5表达方式

2如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量的值计算的值未排序 对象,则行为未定义。如果存在多个允许的订单 表达式的子表达式,如果这样一个未排序的边 在任何订单中都会产生影响。84)
84)本段呈现未定义的语句表达式,如

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

    i = i + 1;
    a[i] = i;
请注意,优先级仅控制运算符和操作数的分组;它不控制评估的顺序

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

 z[i] = ++i;
是未定义的行为

引自

1) 如果标量对象上的副作用相对于 对同一标量对象的另一个副作用是 未定义

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

见问题3.1至3.9。这些几乎是所有与你的问题类似的问题的答案

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

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


=
运算符不是序列点。赋值语句将调用UB。学习的好方法。。继续保持下去。@KingsIndian看,这比每周更频繁;)@丹尼尔菲舍尔的确如此;-)在本例中,
i
只被修改一次。但它也被用于相对于增量不排序的值计算中,这也会导致未定义的行为。

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