为什么下面这段 C 代码打印出来12 12 12
int main(int argc, char const *argv[]) {
int a = 2, *f1, *f2;
f1 = f2 = &a;
*f2 += *f2 += a += 2.5;
printf("%i %i %i\n", a, *f1, *f2);
return 0;
}
为什么下面这段 C 代码打印出来12 12 12
int main(int argc, char const *argv[]) {
int a = 2, *f1, *f2;
f1 = f2 = &a;
*f2 += *f2 += a += 2.5;
printf("%i %i %i\n", a, *f1, *f2);
return 0;
}
*f2 += *f2 += a += 2.5;
此行具有未定义行为,因为您在同一表达式中多次更改*f2
(ie ) 的值,而没有插入序列点。a
UB 意味着你的程序可能会打印“Hello World”,它可能会崩溃,它可能会打印12 12 12
,或者12 12 1029
它可能会开始吃掉你的大脑。不要依赖未定义的行为。
引用 C++ 标准(我知道问题被标记为 C,但我没有 C 标准,而且我知道 C 中也有同样的规则)
除非另有说明,单个运算符的操作数和单个表达式的子表达式的求值顺序以及副作用发生的顺序是未指定的。53) 在前一个和下一个序列点之间,一个标量对象应修改其存储值最多一次通过表达式的评估。此外,只能访问先验值以确定要存储的值。对于完整表达式的子表达式的每个允许排序,都应满足本段的要求;否则行为未定义。
它为所有人打印出相同的值,因为您只指向一个int
变量:a
.
它打印出来12
是因为a + 2.5 = 4
(a
是int
),然后你将它添加到自身两次。
@Downvoters:为什么这么消极?我想我的回答说明了这个编译器在这个示例代码上做了什么,这应该有助于 OP 理解行为。我同意Armen Tsirunyan的回答是正确的(即应该打勾)并且根据标准未定义行为。但是标准已经实现了,我还没有看到一个编译器编译代码然后在运行时突然举手说Undefined behaviour!
.
I 因为*f2
and*f1
指向a
(一个整数)。
所以*f2 = &a = 2
和*f1 = &a = 2
此时您添加到 a 的值2.5
(因为a
是整数,您将获得4
)。
比你有
a = 4
f2 = 4
f1 = 4
此时你做f2+f1+a = 12.