a = a || expr;
如果 a
没有被设置,expr
会被评估并将结果分配给 a
。 这依赖于逻辑 OR 的短路功能。
当然,上述内容的更短的编写方式是:
a ||= expr;
但是(令我惊讶的是),C语言没有逻辑赋值运算符。
所以我的问题有两个方面。首先,在标准C中是否有更短的方式来编写第一个语句(三元运算符甚至更差 - a = a?a:expr
要求我将a
拼写三次)。
其次,为什么C语言没有逻辑赋值运算符?我能想到的可能原因是:
- 它使语法更难解析?
- 在处理这些情况时存在一些短路的细微差别?
- 认为它是多余的(但这不是反对所有运算符分配的论点吗?)
编辑
请解锁此问题,因为:
它被链接到的问题(作为所谓的重复问题)未得到回答。那个问题的(已接受的)答案表明
||=
不存在,因为它会重复|=
的功能。那是错误的答案。|=
不进行短路计算。C和C ++不是相同的语言。我想知道为什么C语言没有它。事实上,像C ++和特别是Java这样的派生语言(它没有遭受像Edmund's答案中所暗示的旧代码问题)使问题更加有趣。
编辑2
现在似乎我的最初意图是错误的。在语句a = a || expr
中(其中a
为整数,expr
返回一个整数值),首先会将a
和expr
隐式转换为“布尔”值,然后将“布尔”值分配给a
。这是不正确的-整数值将丢失。感谢Jens和Edmund。
因此,关于第一个问题,正确的方式不是替代方式 :) ,可以编写以下代码来实现我的意图:
if (!a) a = expr;
或者a = a ? a : expr;
我认为它们应该被同样地优化,尽管个人而言我更喜欢第一个(因为它少输入了一个a
)。
然而,问题的第二部分仍然存在。Jens和Edmund所提出关于a ||= expr
中歧义性的论点同样适用于a = a || expr
。赋值情况可以简单地视为正常情况:
- 将
a
转换为布尔值 - 如果它是true,整个表达式的值等于
a
的布尔值 - 否则,求值
expr
,将结果转换为布尔值,赋值给a
并返回它
上述步骤似乎对赋值和正常情况都一样。
||=
等语法简写。而这个问题问的是为什么C语言不允许通过布尔运算符传递非布尔值的技巧。 - Edmundif ( ! a ) a = expr;
,它非常清晰简洁。至于技巧,需要注意的是布尔值的加法和乘法分别产生 OR 和 AND 函数,因此只要不需要短路或强制转换为bool
,+=
和*=
的效果就像||=
和&&=
。 - Potatoswattera |= expr
中应该分配什么值,expr
的结果还是它的逻辑值?作为一个整体,a |= expr
的类型应该是什么,int
、a
的类型还是提升a
和expr
的结果?我认为这些问题没有直接的解决方案,可能因此任何可能考虑过这个问题的人都很快就放弃了。我个人会选择a = (a ? a : expr)
并让编译器优化赋值。 - Jens Gustedta ?: b
,它的意思是a ? a : b
,但不会进行额外的求值。 - M.M&&=
和||=
运算符对编译器的复杂度没有任何显著影响,就像+=
一样容易实现。更重要的是这些运算符的实用性非常有限。你提出了一个问题:||
或&&
的结果始终为 0 或 1,因此赋值运算符将有条件地使用 0 或 1 覆盖 LHS,具体取决于 LHS 中的值是否类似 true(非零)或 false(零),以及 RHS 是否评估为 true 或 false。我不记得曾经感到缺少这样的功能。 - Jonathan Leffler