以下代码是否在C
?
int a = 1, b = 2;
a = b = (a + 1);
我知道以下 调用UB:
a = b = a++;
原因是它违反了标准中的以下条款:
在前一个和下一个序列点之间,一个对象应该具有它 通过表达式的评估,最多修改一次存储值。 此外,只能访问先前值以确定 值存储。
但是,第一个代码段并未违反此条款。同事说声明a = b = a+1
可能意味着
a = a + 1;
b = a + 1;
或
b = a + 1;
a = b;
我认为由于=
的“从右到左”的关联性,它始终必须是a = (b = (a+1))
,而不是
a = a + 1;
b = a + 1;
但是,我并不积极。是UB吗?
答案 0 :(得分:11)
恕我直言,a = b = a+1
定义明确。
下面。在a
的情况下,您只是使用它来更改 a+1
的值。
明确地说,根据=
运算符的"right-to-left" associativity,您可以将上述内容细分为,
b = a + 1; //a does not change here, only the value is used.
a = b;
答案 1 :(得分:4)
这是C99的完整序列点列表(改编自C99,附件C):
&&
,||
,?:
,,
; for
语句中的每个表达式,或{{1的控制表达式},if
,switch
或while
声明); do
和bsearch()
。从这个角度考虑你的代码:
qsort()
有序列点
int a = 1, b = 2;
a = b = (a + 1);
(完整声明者)之后a = 1
(完整声明者)之后整个b = 2
是单个表达式语句,它不包含内部序列点。但是,它并没有违反禁止在序列点之间对其值进行多次修改的对象:a = b = (a + 1)
和a
在整个语句中都被修改了一次。
答案 2 :(得分:3)
a = b = a + 1;
与:
b = a + 1;
a = b;
您不会更改右侧的左侧值,因此定义良好。
答案 3 :(得分:2)
a = a++;
与
相比有所不同a = a+1;
在第二种情况下,您不是通过执行a
来修改a+1
的值,而在第一种情况下,a
的值正在被更改,这将导致未定义的行为。