如何在c中检查该行为是否未定义?

Old*_*ool 7 c undefined-behavior sequence-points

我知道以下是未定义的,因为我试图在同一个表达式中读取和写入变量的值,即

int a=5;
a=a++;
Run Code Online (Sandbox Code Playgroud)

但如果是这样,那么为什么以下代码片段未定义

int a=5;
a=a+1;
Run Code Online (Sandbox Code Playgroud)

在这里我也试图修改它的值a并同时写入它.

还解释了为什么标准没有解决这个问题或者删除这个未定义的行为,尽管事实上他们知道它是未定义的?

hac*_*cks 6

为什么以下代码片段未定义

int a=5;
a=a+1;  
Run Code Online (Sandbox Code Playgroud)

标准规定了这一点

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算来修改一次.此外,只能访问先前值以确定要存储的值.

如果是a = a + 1; a仅被修改一次,并且a访问的先前值仅用于确定要存储的值a.
而在以下情况下a=a++;,a被修改不止一次 - 由++子表达式中a++=操作符和操作符将结果分配给左侧a.现在没有定义将由哪个++或哪个修改=首先进行.

-Wall在编译第一个代码片段时,几乎所有带有标志的现代编译器都会发出警告,如:

[Warning] operation on 'a' may be undefined [-Wsequence-point]
Run Code Online (Sandbox Code Playgroud)

进一步阅读:我如何理解本节中的复杂表达式,并避免编写未定义的表达式?


小智 6

它未定义的原因不是你读写,而是你写了两次.

a++意味着在读取之后读取并增加它,但我们不知道++是否会在赋值之前发生=(在这种情况下,=将用旧的a值覆盖)或之后,在这种情况下,a将递增.

只是用a++;:)

a = a + 1 没有问题因为只写了一次.


Jus*_*ous 3

长话短说,您可以在标准中找到每个定义的行为。此处未定义的所有内容都是未定义的。

对您的示例的直观解释:

a=a++;
Run Code Online (Sandbox Code Playgroud)

您希望a在一条语句中两次修改该变量。

1) a= //first time
2) a++ //second time
Run Code Online (Sandbox Code Playgroud)

如果你看这里:

a=a+1;
Run Code Online (Sandbox Code Playgroud)

您只修改变量 a 一次:

a= // (a+1) - doesn't change the value of a
Run Code Online (Sandbox Code Playgroud)

为什么标准不定义a=a++行为?

可能的原因之一是:编译器可以执行优化。在标准中定义的情况越多,编译器优化代码的自由度就越小。由于不同的体系结构可以具有不同的递增指令实现,因此编译器不会使用所有处理器指令,以防它们破坏标准行为。或者在某些情况下,编译器可以更改计算顺序,但如果您想修改某些内容两次,此限制将迫使编译器禁用此类优化。