我需要编写表单
的语句a = a || expr;
应评估expr
,并将结果分配给a
iff a
未设置。这取决于逻辑OR的短路能力。
写上述内容的较短方式当然是
a ||= expr;
但是(令我惊讶的是)C没有逻辑赋值运算符。
所以我的问题是双重的。首先,是否有更短的方法来编写标准C中的第一个语句(三元运算符更糟糕 - a = a ? a : expr
要求我拼出a
三次)。
其次,为什么C中没有逻辑分配?我能想到的可能原因是:
编辑
请解锁此问题,因为:
与之相关的问题(作为所谓的副本)尚未得到答复。该问题的(已接受)答案表明||=
不存在,因为重复了|=
的功能。这是错误的答案。 |=
不会短路。
C和C ++不是同一种语言。我想知道为什么C没有它。实际上,像C ++这样的衍生语言,特别是Java(没有像Edmund的答案中提到的遗留代码问题那样)这个问题使得这个问题更加有趣。
编辑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
转换为布尔值a
的布尔值expr
,将结果转换为布尔值,分配给a
,然后将其返回上述步骤对于作业和正常情况似乎都是相同的。
答案 0 :(得分:5)
a ||= expr
的短路评估, a = a || expr
存在问题。
让a ||= expr
函数如a = a || expr
考虑OP的断言:
"在陈述
a = a || expr
...中,首先将a和expr隐式转换为"布尔","
这不太正确。如果expr
评估为a
,则不会转换true
。如果expr
类似于scanf()
或rand()
或某些影响程序状态的函数,这会有所不同。
a ||= scanf("%d", &i) != 1;
之类的代码只会尝试在a
中使用false值扫描数据。虽然可以通过这种方式扩展语言,但是当前||
和&&
集合的其他短路运算符可能会导致编码问题,而不是简单的简化。
另一方面:一种快速的,如果模糊的方式来编写代码,其中函数在出错时返回非零代码。
// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2(); // Only valid if C was extended with &&=
error &&= foo3();
答案 1 :(得分:3)
我想简单的答案是||
是一个布尔运算符:在C中,“boolean”是0或1.操作数被隐式转换为布尔值(我没有检查过那是什么规范实际上说,但它是C的行为方式),结果是布尔值。
改变语义以支持这种模式可能是可行的 - 直到有人依赖||
做它总是做的事情。
答案 2 :(得分:3)
我找不到任何特殊原因,为什么运营商不存在(在C99中)。
所以我能找到的唯一原因是,C89中没有布尔类型,那些布尔运算符只能在if
中使用。
示例:
int i = 5;
/* This should not make any difference,
since or'ing with false, shouldn't change
the value... dib di dib diddy...*/
i ||= 0; /* Actually: i = i || 0, which gives 'true' */
i
现在为'1',对于大多数人来说这非常直观。
如果没有布尔类型,这个运算符显然不会带来任何清晰度或编码改进,这会使得另一个运算符出现。或者
在我看来,a ||= b;
作为if(!a) a = b;
的实施将非常简单,并且已经通过例如{{1}}实施。 LUA。
所以你的问题似乎有点儿,为什么C的设计方式与它的设计方式相同。 如果这个问题是关于C ++的话,你可以问Bjarne Stroustrup然后问他,进入他的是什么。既然事实并非如此,那么在我看来这似乎是一种死路,因为标准已经写了很久以前你不能再问人了,为什么h ***。
另一方面,这个不完整的算子集应该(在我看来)整数使用与你的相似的符号,因为在我看来,没有理由反对它。
我希望我能帮一点点。
答案 3 :(得分:2)
因为运算符||
和&&
的返回类型与其左参数的类型不同。
||
和&&
的返回类型始终为int
1 ,而左参数可以是任何整数,浮点或指针类型。操作数也不必是同一类型。因此,将x ||= y
定义为x = x || y
和将x &&= y
定义为x = x && y
,与其他扩充分配一致,将无法将结果存储在大多数类型的参数中。
您可以提出其他定义,例如: x ||= y
为if(!x) x = y
,x &&= y
为if(!y) x = y
,但这并不是非常明显, 有用,因此不包括在内
1 在C ++中它是bool
。