未排序的修改警告
Unsequenced modification warning
我正在读一本 C 语言的书,但我陷入了这个例子。
作者说这个例子的结果是 x == 0 和 y == 101.
我对 y 结果很好,但是我真的认为表达式中的第一件事会计算 y == y然后将递增 y +1.
我编译了代码并得到了一个警告:未排序的修改并且1被存储在x中。
这是什么原因?
int main(void)
{
int x,y=100;
x=y;
x= y == y++;
printf ("%d %d",x,y);
return 0;
}
C 中的一个表达式,包括另一个表达式的子表达式,可能有两种作用:
- 一个主要作用:它产生一个值以在包含表达式中进一步使用。
- 副作用:它修改对象或文件或访问易失性对象。
一般来说,C标准并没有说什么时候会出现副作用。 不一定在评价主效应的同时出现
在x = y == y++;
中,y++
有修改y
的副作用。但是,y
也用作 ==
的左操作数。因为 C 标准没有说明副作用何时会发生,它可能会在使用左操作数 y
的值之前、期间或之后发生。
C 标准中的一条规则指出,如果使用对象的值相对于对该对象的修改没有排序(指定发生在之前或之后),则行为是未定义的。此外,如果两个修改相对于彼此没有排序,则行为未定义。
此规则的最初动机是 y++
的增量 y
可能需要多个步骤。在只有 16 位运算的计算机中,C 实现可能支持 32 位 int
通过使用多条指令获取 y
的低 16 位,将它们加 1,记住进位,存储结果16位,得到y
的高16位,加上进位,存储结果位。如果其他一些代码单独尝试获取 y
的值,它可能会在加 1 之后获取低 16 位,但在进位之前获取高 16 位,结果可能是y
的值既不是添加前的值(例如, 0x1ffff)也不是添加后的值(例如&, 0x20000) 但混合 (0x10000)。你可以说一个实现应该跟踪对象上的操作并将它们分开,这样就不会发生这种交错。但是,这会给编译器带来负担并干扰优化。
在表达式 y == y++
中,表达式 y
和 y++
的求值顺序是 未排序的 或者,更简单地说,未指定顺序。
但是,这里的结果取决于表达式的计算顺序。因此,编译器会发出诊断信息。
我正在读一本 C 语言的书,但我陷入了这个例子。
作者说这个例子的结果是 x == 0 和 y == 101.
我对 y 结果很好,但是我真的认为表达式中的第一件事会计算 y == y然后将递增 y +1.
我编译了代码并得到了一个警告:未排序的修改并且1被存储在x中。
这是什么原因?
int main(void)
{
int x,y=100;
x=y;
x= y == y++;
printf ("%d %d",x,y);
return 0;
}
C 中的一个表达式,包括另一个表达式的子表达式,可能有两种作用:
- 一个主要作用:它产生一个值以在包含表达式中进一步使用。
- 副作用:它修改对象或文件或访问易失性对象。
一般来说,C标准并没有说什么时候会出现副作用。 不一定在评价主效应的同时出现
在x = y == y++;
中,y++
有修改y
的副作用。但是,y
也用作 ==
的左操作数。因为 C 标准没有说明副作用何时会发生,它可能会在使用左操作数 y
的值之前、期间或之后发生。
C 标准中的一条规则指出,如果使用对象的值相对于对该对象的修改没有排序(指定发生在之前或之后),则行为是未定义的。此外,如果两个修改相对于彼此没有排序,则行为未定义。
此规则的最初动机是 y++
的增量 y
可能需要多个步骤。在只有 16 位运算的计算机中,C 实现可能支持 32 位 int
通过使用多条指令获取 y
的低 16 位,将它们加 1,记住进位,存储结果16位,得到y
的高16位,加上进位,存储结果位。如果其他一些代码单独尝试获取 y
的值,它可能会在加 1 之后获取低 16 位,但在进位之前获取高 16 位,结果可能是y
的值既不是添加前的值(例如, 0x1ffff)也不是添加后的值(例如&, 0x20000) 但混合 (0x10000)。你可以说一个实现应该跟踪对象上的操作并将它们分开,这样就不会发生这种交错。但是,这会给编译器带来负担并干扰优化。
在表达式 y == y++
中,表达式 y
和 y++
的求值顺序是 未排序的 或者,更简单地说,未指定顺序。
但是,这里的结果取决于表达式的计算顺序。因此,编译器会发出诊断信息。