我有小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
谢谢和问候, 卡皮尔
答案 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明确定义)是未定义的行为。
在两个序列点之间,对象被多次修改,或者被修改并且读取先前值而不是确定要存储的值