C 关于序列点和UB
有一个问题我无法解释清楚C 关于序列点和UB,c,undefined-behavior,C,Undefined Behavior,有一个问题我无法解释清楚 哪种选择是错误的,为什么 (A) a += (a++); (B) a += (++a); (C) (a++) += a; (D) (++a) += (a++); A和B之间有什么区别 我的理解是: A是UB,但B是可以的,因为++A的副作用将在作业之前完成。是这样吗 更新:序列点内++a和a++之间有什么区别?预增量(减量)的副作用可能在下一个seq点之前的任何时间完成,就像后增量(减量)一样 哪种选择是错误的,为什么 (A) a += (a++); (
哪种选择是错误的,为什么
(A) a += (a++);
(B) a += (++a);
(C) (a++) += a;
(D) (++a) += (a++);
A
和B
之间有什么区别
我的理解是:
A
是UB,但B
是可以的,因为++A
的副作用将在作业之前完成。是这样吗
更新:序列点内++a
和a++
之间有什么区别?预增量(减量)的副作用可能在下一个seq点之前的任何时间完成,就像后增量(减量)一样
哪种选择是错误的,为什么
(A) a += (a++);
(B) a += (++a);
(C) (a++) += a;
(D) (++a) += (a++);
所有这些都是错误的,这是因为前两个调用未定义的行为,后两个不编译。(如果他们这样做了,他们也会调用UB。)
哪种选择是错误的,为什么
(A) a += (a++);
(B) a += (++a);
(C) (a++) += a;
(D) (++a) += (a++);
所有这些都是错误的,这是因为前两个调用未定义的行为,后两个不编译。(如果他们这样做了,他们也会调用UB。)第一个和第二个是UB,因为C没有定义应该首先计算什么 第三个和第四个不编译-原因:
赋值的左操作数需要左值
让我更具体地谈谈前两个问题:
a++=(a++)代码>-等于a=a+(a++)代码>
- 如果首先计算
a++
,则它是a=a+1+a代码>
- 如果在末尾计算
a++
,则它是a=a+a代码>
但是C没有定义应该首先发生什么,所以它取决于实现,这是UB
第二个也是一样。第一个和第二个是UB,因为C没有定义应该首先计算什么
第三个和第四个不编译-原因:赋值的左操作数需要左值
让我更具体地谈谈前两个问题:
a++=(a++)代码>-等于a=a+(a++)代码>
- 如果首先计算
a++
,则它是a=a+1+a代码>
- 如果在末尾计算
a++
,则它是a=a+a代码>
但是C没有定义应该首先发生什么,所以它取决于实现,这是UB
第二个问题也是如此。选择题@德夫努尔:是的。但是我想知道清楚的原因。看看选项a++=(++a)代码>这样a=a+++a代码>括号在所有语句中都是不必要的,但没有坏处。@JonathanLeffler(再次强调,运算符优先级与求值顺序不同。)选择题@德夫努尔:是的。但是我想知道清楚的原因。看看选项a++=(++a)代码>这样a=a+++a代码>括号在所有语句中都是不必要的,但没有坏处。@JonathanLeffler(同样,运算符优先级与求值顺序不同)。为什么第二个是UBa++=(++a)
等于++a;a+=a代码>@Donglei哦哈?是的,我知道作业不是序列点。你能解释一下序列点内++a
和a++
之间的区别吗?我的理解是:在返回之前,预增量将++
,所以在++a
之后,副作用已经发生了。@Donglei,副作用何时发生并不重要,因为无论哪种方式,a
都会在序列点之间修改两次。是的,完全正确。但是序列点内++a
和a++
之间的区别是什么?我想这就是我所困惑的。为什么第二个是UBa++=(++a)
等于++a;a+=a代码>@Donglei哦哈?是的,我知道作业不是序列点。你能解释一下序列点内++a
和a++
之间的区别吗?我的理解是:在返回之前,预增量将++
,所以在++a
之后,副作用已经发生了。@Donglei,副作用何时发生并不重要,因为无论哪种方式,a
都会在序列点之间修改两次。是的,完全正确。但是序列点内++a
和a++
之间的区别是什么?“我想这就是我所困惑的。”乔纳坦利弗勒:它能让恶魔从你鼻子里飞出来吗?XDIt取决于编译器编写人员的技能!我删除了我的评论;我对它还不够满意。让我们把这两个也去掉。@JonathanLeffler它能让恶魔从你鼻子里飞出来吗?XDIt取决于编译器编写人员的技能!我删除了我的评论;我对它还不够满意。让我们把这两个也去掉。