I had the need to code a statement of the form
a = a || expr;
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.
The shorter way to write the above would, of course, be
a ||= expr;
but (to my surprise) C does not have logical assignment operators.
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).
Secondly, why aren't there logical assignments in C? The possible reasons I could think of are:
EDIT
Please unlock this question because:
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 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.
EDIT 2
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;
or
a = a ? a : expr;
they should be optimized the same (I think) though personally I would prefer the first one (because it has one less a
to type).
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
to booleana
expr
, convert result to boolean, assign to a
, and return itThe steps above seem to be the same for both the assignment and normal case.
Assignment Operators in C/C++ Assignment operators are used to assigning value to a variable. The left side operand of the assignment operator is a variable and right side operand of the assignment operator is a value.
The “not” (!) The “not” logical operator is used to convert a value from true to false, or from false to true. Similarly, if an operand evaluates to true, a logical “not” would cause it to evaluate to false. If an operand evaluates to false, its logical “not” equivalent would be true.
An assignment operator is the operator used to assign a new value to a variable, property, event or indexer element in C# programming language. Assignment operators can also be used for logical operations such as bitwise logical operations or operations on integral operands and Boolean operands.
The logical-OR operator performs an inclusive-OR operation on its operands. The result is 0 if both operands have 0 values. If either operand has a nonzero value, the result is 1. If the first operand of a logical-OR operation has a nonzero value, the second operand isn't evaluated.
a ||= expr
is problematic due to short circuit evaluation of its equivalent a = a || expr
.
To have a ||= expr
function like a = a || expr
consider OP's assertion:
"In the statement
a = a || expr
..., first both a and expr will be implicitly converted to "booleans","
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.
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();
Because the return type of operators ||
and &&
is not the same as type of their left argument.
The return type of ||
and &&
is always int
1, while the left argument may be any integral, floating point or pointer type. The operands also don't have to be of the same type. Therefore defining x ||= y
as x = x || y
and x &&= y
as x = x && y
as would be consistent with other augmented assignments would not be able to store the result in the argument for most types.
You could come up with other definitions, e.g. x ||= y
as if(!x) x = y
and x &&= y
as if(!y) x = y
, but that would not be exactly obvious and it is not that useful, so it was not included.
1In C++ it is bool
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With