逻辑运算符和赋值运算符之间的计算顺序 [重复]

Order of evaluation between logical and assignment operators [duplicate]

提问人:Kain3 提问时间:10/19/2023 最后编辑:LundinKain3 更新时间:10/19/2023 访问量:101

问:

我知道 C 中运算符的计算顺序和优先级是独立的。但是,当有多个运算符强制执行评估顺序时,我会感到困惑。

例如:

a = b && c || d;

解析为:

a = ((b && c) || d);

编译器如何评估这一点?

它是否计算 ,(如有必要)评估 ,然后评估从右到左的赋值运算符?(b && c)d

还是先计算赋值运算符,然后评估运算符,然后(如有必要)计算?&&d

C 惰性 算子优先级 评估 短路

评论

1赞 Weather Vane 10/19/2023
这里可以看出,它的优先级高于 。&&||
0赞 Kain3 10/19/2023
是的,我理解这一点,但这不一定会影响评估的顺序,不是吗?它只是将 (b&&c) 视为单个变量。由于赋值运算符要求左右计算顺序,我只想知道它是如何计算的,因为我们有逻辑运算符和赋值运算符。(赋值优先或逻辑优先)
0赞 Toby Speight 10/19/2023
@WeatherVane,asker 似乎很好地掌握了优先级,但希望了解评估顺序
0赞 Fe2O3 10/19/2023
我理解这个问题的方式是 OP 是混淆的,思考运算符是计算的,而不是左值/右值项(这里表示为变量)。

答:

1赞 Toby Speight 10/19/2023 #1

在 C 语言中,大多数情况下,未指定计算顺序。

在这种情况下,我们有逻辑运算符,它们确实有序列点:例如,在开始计算之前被完全评估。bc

赋值运算符没有序列点,因此可以在赋值之前或之后进行计算。a

这就是为什么修改在此类运算符的两端使用的变量是不安全的(例如 未定义)。*++i = *i

评论

0赞 Kain3 10/19/2023
当你说 a 是“计算的”时,它是否意味着获取变量的内存?
0赞 Toby Speight 10/19/2023
对于运算符来说,计算是确定存储值的位置。如果只是一个变量的名称,那么这个计算是微不足道的。但是,如果是其他表达式(例如在示例中),则涉及更多的计算。=aa*++i
0赞 Kain3 10/19/2023
A 左值正确吗?而且我认为 lvalues 中不能有表达式。
0赞 Toby Speight 10/19/2023
这就是你错的地方。作为简单的近似值,左值表达式是可以出现在赋值左侧的表达式(因此是 l),右值表达式可以出现在右侧 (r)。许多表达式可以在任一上下文中计算 - 例如 .array[index]
1赞 tstanisl 10/19/2023 #2

从 6.5.16p3 开始

赋值运算符将值存储在左操作数指定的对象中。赋值表达式在赋值后具有左操作数的值,111),但不是左值。赋值表达式的类型是左操作数在左值转换后的类型。更新左操作数存储值的副作用在左操作数和右操作数的值计算之后进行排序。操作数的计算是未排序的。

因此,C标准没有规定评估和评估的顺序。此外,如果结果取决于评估顺序,则行为是未定义的。a((b && c) || d)

只能说:

  • b在评估之前进行评估,如果评估结果为零,则从不进行评估。ccb
  • b && c在返回非零值之前计算或不计算。dd(b && c)
  • 由 L 值表达式指定的对象在两者之后分配并进行计算。a((b && c) || d)a