今天我正在摆弄Code Blocks并收到一条好奇的警告信息。这不是一个错误,它编译并运行预期的结果,但警告信息引起了我的好奇心。
代码:
while (i < right)
*(array + i) = *(buffer - left + i++);
和
while (i >= 0 && *(array + i) > key)
*(array + i + 1) = *(array + i--);
给我一些错误消息,如:
警告:'i'上的操作可能未定义
但类似的代码:
if (l < left + middle &&
(r == right || min == *(array + l)))
*(buffer + i) = *(array + l++);
else
*(buffer + i) = *(array + r++);
未导致警告消息。请注意,所有代码段都来自同一个项目/文件。
答案 0 :(得分:3)
赋值运算符不会导致序列点。因此,这一行:
*(array + i + 1) = *(array + i--);
在没有插入序列点的情况下访问/修改i
两次。这是你被警告的未定义行为。语言无法保证您在左侧i
获得的价值。
答案 1 :(得分:1)
这是undefined behavior,因为您要修改i
并在sequence points之间的另一个操作数中访问i
的先前值,例如:
*(array + i) = *(buffer - left + i++);
^^ ^^^
6.5
表达式段 2 中的C99标准草案说:
在上一个和下一个序列点之间,对象应具有其存储值 通过表达式的评估最多修改一次.72)此外,先前值 应只读以确定要存储的值 .73)
并在脚注73 中提供了以下未定义行为的示例:
i = ++i + 1;
^^ ^^^
a[i++] = i;
注意,第一个示例与前面代码中指出的示例类似。