use*_*550 3 c conditional-operator unary-operator sequence-points postfix-operator
#include<stdio.h>
int main()
{
int a=4;
int b=4;
int c= a++ < ++b? 1 : 0;
printf ("%d",c);
}
Run Code Online (Sandbox Code Playgroud)
已知在 处有一个序列点?,这意味着前缀和后缀操作都必须在该点完成。还知道(?)b在比较之前增加。然而,是a在比较之前还是之后增加呢?
如果在测试之前递增<,则布尔值计算结果为 false 并c设置为 0,否则为 true 并c设置为 1。在我的编译器中,它计算结果为 true,这意味着a++在比较操作之后执行并c设置为1.
但这种行为是规范的一部分吗?
我修改为
#include<stdio.h>
int main()
{
int a=4;
int b=4;
int d=2;
int c= a++ + d < ++b + d? 1 : 0;
printf ("%d",c);
}
Run Code Online (Sandbox Code Playgroud)
它的计算结果仍然为 1。后缀必须在 之前完成?,但这真的确保它在比较之后发生吗<?
a++返回增量a 之前的值。返回增量后++b的值。因此,这会减少到减少到 哪一个为真,因此表达式的计算结果为。b 4 + 2 < 5 + 26 < 7a++ + d < ++b + d ? 1 : 01
由于 和a都b没有在表达式中使用多次,因此不存在未定义的行为。
还知道(?) b 在比较之前递增。然而,a是在比较之前还是之后递增呢?
这是一个微妙的观点,但了解这里到底发生了什么很重要。
子表达式a++和 都++b做两件事。它们计算要在周围表达式中使用的新值,并更新正在操作的变量的存储值。
这也是如此a++:
a到周围的表达式a。并++b这样做:
b它向周围的表达式产生 (4+1 或 5) 的新值b。<请注意,在这两种情况下,操作员关心的是事情 1 。而且,在这两种情况下,事情 1 都是绝对定义,它不依赖于时间。
或者,换句话说,询问“ a/是b在比较之前还是之后递增?” 这不是一个真正正确的问题。价值观a和b+1参与比较,仅此而已。
时间出现的地方是事情 2。我们不确切地知道新值何时存储回a。我们也不知道新值何时存储回b. 我们所知道的是,这些存储将在下一个序列点之前的某个时间发生(正如您正确地注意到的那样,在本例中是?三元运算符的一部分)。
但一切都不取决于这些时间,因此这里没有未定义的行为。
当以下任一情况时,就会出现未定义的行为
a或b) 也有其值在表达式的其他地方独立使用,这意味着我们不知道该使用是使用旧值还是新值但是,同样,这些问题都没有在这里发生,因此表达式是明确定义的。