This question already has answers here:
What does the "=!" operator do? [closed]
(6 answers)
Closed 9 years ago.
I was surprised by this code:
if (a =! b) { // let it be on false
...
}
But a is never assigned by a value. What's this operator about?
That's two operators, = and !, not one. It might be an obfuscated way of writing
a = !b;
if (a) {
// whatever
}
setting a to the logical inverse of b, and testing whether the result is true (or, equivalently, whether b was false).
Or it might be a mistyping of a != b.
Long ago, when dinosaurs roamed the earth and C ran on 5th edition UNIX on PDP-11s, =! was the 'not equals' operator. This usage was deprecated by the creation of Standard C, so now it means 'assign the logical inverse', as in a = !b. This is a good argument for always surrounding binary operators with spaces, just to make it clear to the humans reading the code what the compiler is thinking.
I'm a bit surprised nobody else mentioned this, but then again I may be the only SO user to have ever touched a C compiler that old.
a is assigned the boolean negation of b in that line. It is just a misformatted
if( a = !b ) {
... and an evil hidden assignment inside a condition.
a =! b
is just a funny way of putting
a = !b
i.e. the assignment of not b to a.
The value of the expression is a after the assignment.
With the code below you can see that the value of the expression a = !b is !false (i.e. true), and you can then see the assignment has taken place by checking the value of a, which is also true.
#include <iostream>
int main()
{
bool a = false;
bool b = false;
if(a)
printf("a is true!\n");
else
printf("a is false!\n");
if(a = !b)
printf("expression is true!\n");
else
printf("expression is false!\n");
if(a)
printf("a is true!\n");
else
printf("a is false!\n");
}
Result:
a is false!
expression is true!
a is true!
Operators in C++
According to C/C++ operators list there is no operator such as =!. However, there is an operator != (Not equal to, Comparison operators/relational operator)
There are two possibilities.
It could be typo mistake as I've noticed that =! operators is in if statement and someone is trying to type != instead of =! because != is the comparison operator which returns true or false.
Possibly, the developer was trying to assign the boolean negation of b to a and he/she has done a typo mistake and forgot to put a space after equal sign. This is how the compiler interprets it, anyways.
According to Operator precedence in c++:
Operator Logical NOT (!) precedence is 3 and Associativity is Right-to-left
Operator Direct assignment (=) precedence is 16 and Associativity is Right-to-left
They are two different operators: the = (assignment) operator together with the ! operator. It can basically be translated to an assignment of a to the negated value of b.
if (a = !b)
But, what the user, probably, meant to write was the != operator:
if (a != b)
That is not a single operator, it is however, a great way to obfuscate code.
If it were written a=!b instead, the white space might not lead you to believe that it was a single operator.
Compilers have warnings for assignment in a conditional expression unless you wrap the entire statement in a set of parenthesis, and this is a perfect example of when this warning would be useful.
Both of these statements are functionally identical, but one generates a warning and the other does not:
if (a =! b) // Generates a warning with `-Wparentheses` (gcc)
if ((a =! b)) // No such warning
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about.
This, of course, assumes that you are a responsible programmer and actually read the warnings your compiler spits out.
Using white space in a more reasonable way, the statement is actually:
if (a = !b) // Assign A the value of (logical) NOT B and then test the truth
The compiler warning mentioned above is actually useful in the case where the person who wrote this code accidentally transposed ! and =. However, from the cryptic inline comments in your original question, a = !b is probably the author's intention.
C++ does not have an =! operator, which immediately means that this is an = operator followed by a ! operator. So, you simply have a = !b in the if condition.
This is all about clarity of code:
It should be written as: if (a = !b)
if (a = !b) is the same as saying if a is assigned to !b. So there are technically 2 separate operators being used, = which is an assignment operation, and ! which is a logical expression.
Just put a space between = and ! it solves this confusion.
There could be three reasons for this:
It could be a mistyping of the != operator, meaning not equal to. Example:
if (a != b) {
// a is not equal to b
}
It could be a mistyping a == !b, meaning a is equal to not b, which would most commonly be used with booleans. Example:
if (a == !b) {
// The boolean a is equal to not b (a is not equal to b)
}
It could be trying to assign a to the inverse of b. Example:
bool a = !b; // Sets a to the opposite of b
I think this is one of the writing or printing mistake. Because if we can not compile this code as it holds a compiletime error. And here this is inside if clause, the return type must be boolean. So how can it possible. The answer is simply a mistake or as Mike said obfuscated way of writing.
And only possible if both variables a and b are boolean which will be compiled as a is equal to (not)b i.e (a = !b) .
This can be taken as a is assigned to !b.
I am trying to answer your question and, in agreement with Mike's answer, I am just adding up.
You can also understand it by a=!!b.
The code a=!b returns 0 to a and a=!!b returns 1 to a.
The =! is not a single operator but the mix of these two.
These types of question are asked to misguide students to check their coding skills.
Related
Probably been answered, but could not find it.
In c++ what does
if(a=b)
mean?
versus
if(a==b)
I just spent two hours debugging to find that
if(a=b)
compiles as
a=b
Why does compiler not flag
if(a=b)
as an error?
In c++ what does if(a=b) mean?
a=b is an assignment expression. If the type of a is primitive, or if the assignment operator is generated by the compiler, then the effect of such assignment is that the value of a is modified to match b. Result of the assignment will be lvalue referring to a.
If the operator is user defined, then it can technically have any behaviour, but it is conventional to conform to the expectations by doing similar modification and return of the left operand.
The returned value is converted to bool which affects whether the following statement is executed.
versus
if(a==b)
a==b is an equality comparison expression. Nothing is assigned. If the types are primitive, or if the comparison operator is generated by the compiler, then the result will be true when the operands are equal and otherwise false.
If the operator is user defined, then it can technically have any behaviour, but it is conventional to conform to the expectations by doing similar equality comparison.
Why does compiler not flag
if(a=b)
as an error?
Because it is a well-formed expression (fragment) as long as a is assignable with b.
if(a=b) is a conventional pattern to express the operation of setting value of a variable, and having conditional behaviour depending on the new value.
Some compilers do optionally "flag" it with a warning.
Note that if you would assign value int a = 1 and you make an if statement
if (a = 2)
{
std::cout << "Hello World!" << std::endl;
}
It still works, even though they are two different values, they will do the std::cout
However if you use a double equals sign == it will not.
The reason for this is if you use the standard double equals sign == you are asking the code if a is equivalent to 2, if it is 2. Obviously it's not, so it doesn't std::cout. But if you use an equals sign, you are changing the value a to 2, so it continues with the if statement.
And, to prove this, try taking away the int a = 1 from before the if statement and add an int before a in the if statement, it works.
I need to write a program in any language, that would print 1 if the language uses short circuit evaluation in the if-then-else operator and 0 if the languages does not.
My question is, what does short circuit evaluation in the if-then-else operator mean?
is it simply the lazy evaluation that occurs in the && and || operators?
If I'm reading this question correctly, then yes. In languages that implement this, if you had a statement like
if (A || B || C || D)
the runtime would stop evaluating as soon as it found a statement that was true. For example, if A and B are false but C is true, it would evaluate A, B, and C but not D. This is important if you do something like this:
if (a != null && a.ToString() == "abc")
The short-circuit behavior means that the second half of this if statement won't be executed if a is, in fact, null, which is critical because if that wasn't the case then this statement could throw a null reference exception. If it wasn't for that you'd have to do something like
if (a != null) {
if (a.ToString() == "abc") {
// ...
which is obviously a lot less concise.
&& behaves in a similar way:
if (A && B && C && D) ...
If A is false, for example, why bother to check the rest of the expressions?
In terms of the assignment, I'll give you a hint: what would happen if you had a side effect in one of the expressions?
In case anyone faces a similar assignment/ would like to know more about short circuiting of the if operator in C:
First, Lets mark each part of the if operator as follows:
if(Expression)? BlockA : BlockB;
Now, in PL C, which follows short circuiting of the if-then-else operator, if the Expression is evaluated to true, then only BlockA is evaluated, otherwise only BlockB is evaluated
Lets assume now that C doesn't follow short circuiting, What happens is that both BlockA and BlockB are evaluated regardless of the evaluation result of the Expression (Sounds stupid and dangerous, but apparently that's how it works)
I am addicted to "braceless" ifs, like this:
if (a) b++, c++, d = e;
But one annoying thing is that return cannot be a part of the last part. Intuitively I feel why is that, but can anyone explain in programming language terms why this will not compile?
main() {
int a, b, c, d, e;
if (a) b = c, d = e, return;
}
If you care, please also explain why is that designed like that, it seems like a flaw to me. I can understand in C but in C++ it could have been redesigned without major compatibility loss with the existing C code.
Just for comparison: these will compile and do exactly what expected:
while (a < 10) a++, b--, c += 2;
while (a < 10) if (a == 5) half = a, save();
The "comma" operator is exactly that, an operator. It's left and right sides must be expressions, and return is not an expression.
To elaborate, the comma operator evaluates its left-hand side first, and discards the value. Then, it evaluates its right-hand side, and the whole comma expression evaluates to the right-hand side's value.
It's similar to this:
template <typename T, typename U>
U operator,(T t, U u)
{
return u;
}
Therefore, you cannot put anything in a comma expression that is not an expression itself.
If you're looking to simultaneously execute a series of statements and group them together, that's exactly what ; and {} are for. There is no reason to duplicate that behavior in the comma operator.
It can be done the following way
if (a) return ( b = c, d = e, 0 );
Oe if there is no return expression
if (a) return ( b = c, d = e, ( void )0 );
It may be open to question whether this answers the question the OP was really asking, but in case anybody cares about why the comma operator was designed the way it was, I think it goes back to BCPL.
In BCPL, you could combine a series of assignments like:
L1 := R1
L2 := R2
...into a single statement (command) like:
L1, L2 := R1, R2
Much like in C and C++, these were executed in order from left to right. Unlike C and C++, this "comma operator" didn't produce a single expression (at least as C uses the term).
BCPL also had a resultis that let you make a block of statements into something almost like a function.
At least to me, it looks like in C, Dennis1 decided decided to sort of combine these two concepts into a single one that was rather simpler: a comma operator that would allow evaluation of a number of expressions in succession, and yield a single result.
Reference: BCPL Reference Manual
I suppose in fairness I should mention the possibility that this decision was actually made by Ken Thomson in the design of B. Little enough documentation on B has survived that it's almost impossible to even guess about that.
As already stated return is not an expression, it's a keyword. However, b = c, d = e is an expression. Therefore your intent is probably this:
if (a) return (b = c, d = e, 0);
b = c, d = e, return doesn't really make any sense, as it would be inconsistent with how the comma operator works in other contexts. Imagine if you could do this:
for (int i = 0, j = 0, return; ...
That would make absolutely no sense. It would also be redundant if return meant something in this context as the comma operator already returns its last operand. There would also be no point because the comma operator already evaluates its operands, how would return something be beneficial in this case?
Someone looking at your code might glance over it and say, "this should be: if (a) (b = c, d = e); return 0;", which is a trap because of the lack of braces. What they would really mean is if (a) { (b = c, d = e); return 0; }, but this problem would be avoided if you use the syntax mentioned at the top of this answer. It simply isn't readable as it makes no semantic sense.
Regardless, this would only make sense if b and d were global variables, for example something like errno, allowing you to assign to the variable and return in one statement.
Why exactly this will not compile if (a) b = c, d = e, return;?
This is because a comma (,) operator must have its left and right operands to be expressions. The return statement is not an expression. See the syntax defined for , operator by the C and C++ standard:
C11: 6.5.17 Comma operator
Syntax
expression:
assignment-expression
expression , assignment-expression
The same syntax is defined by C++ standard
C++: 5.18 Comma operator [expr.comma]
The comma operator groups left-to-right.
expression:
assignment-expression
expression , assignment-expression
A pair of expressions1 separated by a comma is evaluated left-to-right;
Note that the standard says about expressions and return is not an expression.
1.Emphasis is mine
I can understand in C but in C++ it could have been redesigned without
major compatibility loss with the existing C code.
It could have been, but why would anyone, ever, want it to be? The language already contains a means to the end that you are looking for- braces. They are much more reliable and useful than abusing the comma operator like you have. For example, if you are using UDTs, then you are going to run into some nasty surprises when I overload the comma operator. Oops!
More to the point, having return as an expression doesn't make sense, because the function has already, well, returned, when it is evaluated, so there's no way anyone could possibly use any hypothetical return value.
Your entire question is predicated on your personal dislike of braces. Nobody else who designs the language really shares that feeling.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I would like to know if one of this two solution is better than the other :
Version 1:
bool myFunction()
{
if (A)
return false;
if (B)
return false;
if (C)
return false;
if (D)
return false;
return true;
}
Version 2 :
bool myFunction()
{
return (!A && !B && !C && !D);
}
I guessed that version 2 may be a bit less efficient as we may have to calculate the whole boolean expression to know if it's true or false. In the first version, if A is false, it returns false, without calculating B, C or D.
But I find second version much more readable.
So what is the best way to do that ?
Thank you.
In the first version, if A is false, it returns false, without calculating B, C or D.
That's true for the second version as well. The && operator is short-circuiting - if the first operand is false, it won't evaluate the second operand.
However, I'd either remove the brackets from the second version:
return !A && !B && !C && !D;
or invert it to:
return !(A || B || C || D);
... depending on which you find simpler to read. I personally prefer to have as few negations as possible. (|| is also short-circuiting, so they're equivalent in efficiency.)
Don't avoid multiple return statements on principle, mind you - there are plenty of times where using multiple return statements gives more readable code. Aim for the most readable code you can, and only worry about efficiency when you've proved that the most readable approach doesn't perform as well as you need it to. In this case, the approaches are equally efficient, so that's not a concern anyway.
It depends. They both do the same thing.
If your function really just returns a simple combination of variables and logical operations, then go for return !A && !B && !C && !D; (the parentheses are unnecessary).
If, however, you are doing long and complex computations, then:
Think about refactoring your code so that one function doesn't in fact do the job of 4 functions;
If everything else fails, insert multiple return statements. It's not that bad. Enforcing a single exit point at all costs is a stupid coding convention. Allowing more than one return statements can indeed make the code readable in some cases (in particular, error handling).
from ISO/IEC 9899:
6.5.13 Logical AND operator
4
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated.
And this one for c++:
from N1905=05-0165
5.14 Logical AND operator
1 The && operator groups left-to-right. The operands are both implicitly converted to type bool (clause 4). The result
is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second
operand is not evaluated if the first operand is false.
So in both cases it doesn't have to calculate the whole expression
I was going through someone elses code and I wasn't able to get the syntax of following
c = x<0 ? x = -x,'L':'R';
and
if(x) x--,putchar(c);
going by the symantics, it is clear that in the first, variable c is assigned 'L' or 'R'.And in the second, both x-- and putchar() are executed. But what exactly is the role of comma operator here??
But what exactly is the role of comma operator here?
In this case, code obfuscation. The original developer probably thought they were being clever.
The comma operator allows you to perform multiple actions in a single statement, but you are almost always better off using 2 statements. In those cases, it expands to:
if( x < 0 ) {
x = -x;
c = 'L';
} else {
c = 'R';
}
and
if(x) {
x--;
putchar(c);
}
The comma operator evaluates both expressions, and returns the value of the last.
The first expression does two things in one statement. If chooses 'L'
or 'R' and also sets x to its negative if 'L' is chosen.
The second expression (the part after the 'if') decrements x and then
puts a character. The meaning of this is unclear without more context.
Readability in both could be improved by using separate statements rather than the comma operator. The first tries to shoehorn an if statement into a conditional expression. But the second is already using an if statement, so it's unclear why the comma operator was chosen at all.
The role of the comma operator in that context is to allow using the conditional operator and write an assignment as part of the evaluation of one of the expressions.
In my opinion, this is just horrible style. An if statement would have better communicated the intent of that code, and would have hardly been less efficient.