简体   繁体   中英

Why does C not have a logical assignment operator?

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:

  • it makes the grammar harder to parse?
  • there is some subtlety in handling short-circuiting for these cases?
  • it was considered superfluous (but isn't that an argument against ALL the operator assignments?)

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 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 a = a || expr . the assignment case can simply be treated as the normal one:

  • 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 to a , and return it

The steps above seem to be the same for both the assignment and normal case.

a ||= expr is problematic due to short circuit evaluation of its equivalent a = a || expr a = a || expr .

To have a ||= expr function like a = a || expr 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();

I cannot find any particular reason, why the operators don't exist (in C99).

So the only reason I can find is, that there was no boolean type in C89, and those boolean operators were intended to be solely used in if 's.

Example:

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 is now '1'', which for most people is pretty counter intuitive.

This operator obviously doesn't bring any clearence or coding improvement without the boolean type, that would make sence being or'd with another one.

In my opinion, the implementation of a ||= b; as if(!a) a = b; would be pretty straightforward and has aleardy been implemented by eg Lua.

So you're question seems to be a bit, why C has been designed the way it has been designed. If this question was about C++, you could for example ask Bjarne Stroustrup and ask him, what had went into him. Since this is not the case, this seems to me to be kind of a dead end, because the standard has been written quite some time ago and you cannot really ask people anymore, why the h***.

On the other hand, this incomplete operator set should (in my opinion) aleardy have been made whole using a similar notation than yours, since in my opinion, there is no reason against it.

I hope I could help a little.

I guess the simple answer is that || is a boolean operator: and in C, a "boolean" is 0 or 1. The operands are implicitly converted to booleans (I have not checked that that's what the spec actually says, but it's how C behaves), and the result is a boolean.

Altering the semantics to support this pattern may well be feasible -- until someone relies on || doing what it's always done.

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 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, eg 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.

1 In C++ it is bool .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM