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(同样,运算符优先级与求值顺序不同)。为什么第二个是UB
a++=(++a)
等于
++a;a+=a@Donglei哦哈?是的,我知道作业不是序列点。你能解释一下序列点内
++a
a++
之间的区别吗?我的理解是:在返回之前,预增量将
++
,所以在
++a
之后,副作用已经发生了。@Donglei,副作用何时发生并不重要,因为无论哪种方式,
a
都会在序列点之间修改两次。是的,完全正确。但是序列点内
++a
a++
之间的区别是什么?我想这就是我所困惑的。为什么第二个是UB
a++=(++a)
等于
++a;a+=a@Donglei哦哈?是的,我知道作业不是序列点。你能解释一下序列点内
++a
a++
之间的区别吗?我的理解是:在返回之前,预增量将
++
,所以在
++a
之后,副作用已经发生了。@Donglei,副作用何时发生并不重要,因为无论哪种方式,
a
都会在序列点之间修改两次。是的,完全正确。但是序列点内
++a
a++
之间的区别是什么?“我想这就是我所困惑的。”乔纳坦利弗勒:它能让恶魔从你鼻子里飞出来吗?XDIt取决于编译器编写人员的技能!我删除了我的评论;我对它还不够满意。让我们把这两个也去掉。@JonathanLeffler它能让恶魔从你鼻子里飞出来吗?XDIt取决于编译器编写人员的技能!我删除了我的评论;我对它还不够满意。让我们把这两个也去掉。