赋值运算符不是序列点有什么好的理由吗?

问题描述 投票:0回答:4

operator =
不作为序列点有什么充分的理由吗?都用 C 和 C++ 语言。

我很难想出反例。

c++ c language-design assignment-operator sequence-points
4个回答
25
投票

根据要求:

一般来说,事物需要一个理由来成为一个序列点。他们不需要一个“不”的理由来成为一个序列点;这是默认值。 例如,由于短路行为,

&&

必须是序列点:如果左侧为假,则右侧

不得评估
。 (这不仅仅是优化;右侧可能会产生副作用,和/或取决于左侧是否正确,如 ptr && ptr->data 所示。)因此,必须先评估左侧,然后再评估右侧,以查看是否应该评估右侧。

这个原因对于

=

来说不存在,因为尽管两边都需要“求值”(虽然两边可以出现的内容有不同的限制:左边必须是左值 -

l 
不代表“左”,顺便说一句;它代表“位置”,就像内存中的位置一样 - 我们不能分配给临时或文字),首先评估哪一侧并不重要 - 正如只要在实际分配之前对双方进行评估即可。
    


0
投票

如果我们正在考虑内置类型,那么我认为这是一件好事。

您不想引入太多序列点,因为这会阻碍优化。



0
投票

示例:

无符号字符foo[100]; typedef struct {int x, int y;} POINT; 点 *p1 = (点*)foo; 点 *p2 = (点*)(&(p1->y));

鉴于上述声明,我认为以下声明具有严格定义的行为,并且不涉及任何未定义的行为。

p1->y = 某个值; // 将 p2->x 设置为某个值 p2->x = 某个值; // 将 p1->y 设置为某个值 *p1 = mystruct; // 将 p2->x 设置为 mystruct.y *p2 = mystruct; // 将 p1->x 设置为 mystruct.x

但是,以下两个语句将涉及未定义的行为:

*p1 = *p2; *p2 = *p1;

如果等号处有序列点,编译器必须比较 p1 和 p2,或者将源操作数复制到临时位置,然后将其复制到目标。然而,该标准明确指出,上述两个语句都被视为未定义行为。该标准要求编译器生成在将结构复制到非重叠结构时正确工作的代码,但对结构重叠时编译器可以执行的操作没有限制。一个编译器,它将处理器发送到一个发送“Frink Rules!”的循环中。每个打开的 TCP 套接字这样做都不会违反标准。


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.