可能重复:
未定义的行为和序列点
正如标准中所定义的,E1 += E2 与 E1 = E1 + E2 几乎相同,只是 E1 只计算一次。因此,此外,将 "p += (*p)++ + c"; 导致未定义的行为?
在 gcc/g++ (4.7 / 4.4) 中尝试以下代码。有 2 种结果:bxxxxx (g++4.7) 或 axbxxx (gcc, g++ 4.4)。如果我们在代码中执行(1)而不是(2),我们只能得到axbxxx。
#include <stdio.h>
int main() {
char s[] = "axxxxx";
char *p = s;
printf("s = %s in the beginning.\n"
"p is pointed at the %d-th char.\n", s, p - s);
//p = p + (*p)++ * 3 + 2 - 'a' * 3; // (1)
p += (*p)++ * 3 + 2 - 'a' * 3; // (2)
printf("p is moved ahead by %d steps\n", p - s);
printf("s = %s after the operation.\n", s);
return 0;
}
我找不到它为什么会导致未定义的行为,也不能断言它是 gcc 的错误。
对于 axbxxx 结果,我也无法理解为什么操作数或后 ++ 会被评估两次(一次获取值,然后保存它)。由于在标准中说“1 ...被添加到它”,我认为地址应该只被评估一次。如果后 ++ 的操作数的地址只计算一次,则表达式的效果将是相同的,尽管赋值执行的顺序如何。
=== 更新 ===
在阅读了第一条评论中链接的文档后,我认为以下规则可能很重要:
"2) 此外,只能访问先验值以确定要存储的值。.
那么,“p = p + (*p)++ * 3 + c”中p的访问是否会被认为是*p的“先验值”的一部分,它与要存储在*p中的值无关?
IMO,这条规则没有被违反。