这是Deep C(幻灯片194)
的示例int a = 41;
a++ & printf("%d\n", a);
该演示文稿声称结果未定义。为什么? a
仅在序列点之间分配一次。我认为a++
和printf
之间的执行顺序是未指定的,因此这将在所有符合规范的编译器上打印41或42,没有未定义的行为。
答案 0 :(得分:5)
在这一行 - a++ & printf("%d\n", a);
中只有一个序列点(不计算函数参数中发生的事情 - 因为a++1
发生在这一行本身) - 修改一个变量并从中读取它单个序列点内的时间是UB。如果从对象读取先前的值但是也有修改,则行为未定义,如i * i++
&&
是一个序列点,如果您感到困惑,&
不是序列点。
序列点是尘埃落定的时间点,到目前为止所见的所有副作用都保证完整。 C标准中列出的序列点是:
在完整表达式的评估结束时(完整的 expression是一个表达式语句,或任何其他表达式 不是任何更大表达式中的子表达式); 在||,&&,?:和逗号运算符;和 在函数调用(在评估所有参数之后,以及在实际调用之前)。
标准规定
在前一个和下一个序列点之间,一个对象应该具有它 通过表达式的评估,最多修改一次存储值。 此外,只能访问先前值以确定 值存储。
答案 1 :(得分:3)
按位运算符&
不会引入序列点,因此确实是未定义的行为。