问题描述
我需要编写以下形式的声明
I had the need to code a statement of the form
a = a || expr;
应评估expr
的位置,并且未设置将结果分配给a
的情况,前提是未设置a
.这取决于逻辑或的短路能力.
where expr
should be evaluated and the result be assigned to a
iff a
is not set. this relies on the logical OR's short-circuiting capabilities.
当然,较短的写法是
a ||= expr;
但是(令我惊讶的是)C没有逻辑赋值运算符.
but (to my surprise) C does not have logical assignment operators.
所以我的问题是双重的.首先,是否有较短的方法可以在标准C中编写第一个语句(三元运算符甚至更糟-a = a ? a : expr
要求我将a
拼写三次).
So my question is twofold. First, is there a shorter way to write the first statement in standard C (the ternary operator is even worse - a = a ? a : expr
requires me to spell out a
thrice).
第二,为什么C中没有逻辑分配?我想到的可能原因是:
Secondly, why aren't there logical assignments in C? The possible reasons I could think of are:
- 它使语法更难解析吗?
- 在这些情况下,处理短路有细微之处吗?
- 它被认为是多余的(但这不是反对所有运算符分配的论点吗?)
编辑
请解锁此问题,因为:
-
与该问题相关的问题(被指控为重复)尚未得到答复.该问题的(接受)答案表明不存在
||=
,因为它重复了|=
的功能.那是错误的答案.|=
不会短路.
The question it has been linked to (as a alleged duplicate of) HAS NOT BEEN ANSWERED. The (accepted) answer to that question states that
||=
is not present because duplicates the functionality of|=
. That is the wrong answer.|=
does not short-circuit.
C和C ++是不同的语言.我想知道为什么C没有它.实际上,诸如C ++尤其是Java的派生语言(没有像Edmund的回答所建议的那样受遗留代码问题的困扰)这一事实使这个问题变得更加有趣.
C and C++ are NOT the same languages. I wish to know why C doesn't have it. In fact, the fact that derived languages like C++ and, particularly, Java (which did not suffer from the problems of legacy code as has been suggested in Edmund's answer) makes the question even more interesting.
编辑2
现在看来我的初衷是错误的.在语句a = a || expr
中(其中a
是整数,而expr
返回整数值),首先a
和expr
都将隐式转换为布尔值",然后将分配布尔值"值到a
.这将是不正确的-整数值将丢失.谢谢Jens和Edmund.
It now seems like my original intent was wrong. In the statement a = a || expr
(where a
is integral and expr
returns an integral value, first both a
and expr
will be implicitly converted to "booleans", and then the "boolean" value will be assigned to a
. This will be incorrect — the integral value will be lost. Thanks, Jens and Edmund.
因此,对于问题的第一部分,编码我的意图的正确方法(而非替代方法:)将会是:
So for the first part of the question, the correct ways, not alternatives :), to code my intention would be:
if (!a) a = expr;
或
a = a ? a : expr;
尽管我个人更喜欢第一个(因为键入的a
少了一个),但它们应该被优化为相同的(我认为).
they should be optimized the same (I think) though personally I would prefer the first one (because it has one less a
to type).
但是,问题的第二部分仍然存在.詹斯(Jens)和埃德蒙(Edmund)关于a ||= expr
中的歧义的论点同样适用于a = a || expr
.分配案例可以简单地视为普通案例:
However, the second part of the question still remains. The arguments that Jens and Edmund about have given about the ambiguity in a ||= expr
apply equally well to a = a || expr
. the assignment case can simply be treated as the normal one:
- 将
a
转换为布尔值 - 如果为true,则整个表达式的值将等于
a
的布尔值. - 否则评估
expr
,将结果转换为布尔值,分配给a
,然后将其返回
- convert
a
to boolean - if it is true, the value of the entire expression becomes equal to the boolean value of
a
- otherwise evaluate
expr
, convert result to boolean, assign toa
, and return it
在分配和正常情况下,上述步骤似乎都是相同的.
The steps above seem to be the same for both the assignment and normal case.
推荐答案
a ||= expr
由于对等效的a = a || expr
进行了短路评估而存在问题.
a ||= expr
is problematic due to short circuit evaluation of its equivalent a = a || expr
.
要具有像a = a || expr
这样的a ||= expr
功能,请考虑OP的断言:
To have a ||= expr
function like a = a || expr
consider OP's assertion:
这不是很正确.如果a
评估为true
,则不会转换expr
.如果expr
是scanf()
或rand()
之类的东西或影响程序状态的某些功能,则将有所不同.
This is not quite correct. expr
will not be converted if a
evaluates to true
. This would make a difference should expr
be something like scanf()
or rand()
or some function that affected the state of the program.
诸如a ||= scanf("%d", &i) != 1;
的代码将仅尝试扫描a
中具有错误值的数据.尽管可以通过这种方式扩展语言,但是对当前的||
和&&
集合使用更多的短路运算符可能会导致比清晰的简化更多的编码问题.
Code such as a ||= scanf("%d", &i) != 1;
would only attempt to scan data with a false value in a
. Although it would be possible to extend the language this way, additional short-circuit operators to the current set of ||
and &&
would likely cause more coding problems than clear simplifications.
另一方面:一种快速(如果混淆)的代码编写方法,其中函数会在错误时返回非零代码.
On the other hand: A quick, if obfuscated, way to write code where functions return non-zero codes on error.
// Perform functions until an error occurs.
bool error = foo1();
error &&= foo2(); // Only valid if C was extended with &&=
error &&= foo3();
这篇关于为什么C没有逻辑赋值运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!