syntactical use of comma operator in C++ - c++

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.

Related

Why it shows error: expected expression before ‘return’?

#include<stdio.h>
int main(void)
{
int x=1,y=0;
x>y?printf("Hello World"):return x;
}
Why it shows error: expected expression before ‘return’?
What is the thing need to be changed here?
Why it shows error: expected expression before ‘return’?
The ternary operator is an operator, requiring three operands. The first operand must be an expression of integer type. The latter two operands must be expressions of type compatible with each other.
A return statement specifies a return value for the function in which it appears, and causes that function to terminate. It is not an expression, and does not evaluate to a value, neither the specified return value or any other. As such, it cannot be an operand of the ternary operator.
The error message is, therefore, expressing that the third operand of the ternary operator is missing, which it is, since the return statement cannot be considered an operand. If it were present, that operand would appear before the return.
What is the thing need to be changed here?
To obtain the logic you appear to want, the thing to change is the ternary operator. Use an if / else statement instead:
if (x > y) {
printf("Hello World");
} else {
return x;
}
Generally speaking, the ternary operator should be avoided. It usually makes code harder to read and understand, with little or no offsetting benefit. You may someday discover a programming context where a ternary is the cleanest, clearest way to go, but anywhere else, use if.
The main theme of the ternary operator is
condition ? value_if_true : value_if_false
The statement evaluates to value_if_true if the condition is met, and value_if_false otherwise.
Read more about 'ternary operator' [https://www.freecodecamp.org/news/c-ternary-operator/]
Try to avoid a ternary operator if your concept is not clear. Try to use if-else.

C - Multiple assignments to same variable in one line

I came across this code line in C:
#define RUNDE(n) ( K ^= Q[n], y = K, K = F(K) ^ xR, xR = y )
Is it valid to assign something to K multiple times? I thought it's invalid to change a variable more than one time in one statement.
Is it valid to assign something to K multiple times?
That's perfectly valid C macro. A comma operator , is used here.
Using , operator you can assign a value to a variable multiple times.
e.g.K = 20, K = 30; This will assign 30 to K overwriting the previous value of 20.
I thought it's invalid to change a variable more than one time in one statement.
Yes it leads to undefined behavior if we try to modify a variable more than once in a same C statement but here first , is a sequence point.
So it's guaranteed that we will be modifying the K second time (K = 30) only when all the side effects of first assignment (K = 20) have taken place.
This is well-defined as the comma operator evaluates its first operand before its second.
However, IMHO this code is horrible and you shouldn't write it. inline functions exist to do things like this; using the preprocessor is just abuse. Sure, you would need to pass some arguments to an inline function, but this is far preferable to relying on names from the surrounding scope.
In C++ this would be regarded as nasty; in C it's permissible as the reliance on the preprocessor is more necessary.
But in either case your expression is perfectly well-defined. The comma operator (which is evaluated from left to right), acts as a sequenced expression separator.
The elegant thing with this macro is that its value is the value of xR = y, which is the final value of y.
But the inelegance of this macro, such as using variable names that are not passed as arguments, probably outweighs any benefits. My inclination is to bin it.
It is a valid comma operator, that perform all statements in sequence, returning the value of the last statement.
That macro is a sequence of assignments, using the last assignment (y or xR) as return value

What's this =! operator? [duplicate]

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.

Why exactly this will not compile if (a) b = c, d = e, return;?

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.

What is the "?" and ":" sequence actually called? [duplicate]

This question already has answers here:
What does the question mark character ('?') mean in C++?
(8 answers)
Closed 9 years ago.
This may be a bonehead question, but I cannot figure out what the ? exp : other_exp sequence is called.
Example:
int result = (true) ? 1 : 0;
I've tried using the Google machine, but it's hard to Googilize for something without knowing what it's called.
Thanks!
It is called the the conditional operator or alternativly the ternary operator as it a ternary operator (an operator which takes 3 operands (arguments)), and as it's usually the only operator, that does this.
It is also know as the inline if (iif), the ternary if or the question-mark-operator.
It is actualy a rather useful feature, as they are expressions, rather than statements, and can therefore be used, for instance in constexpr functions, assigments and such.
The C++ Syntax is;
logical-or-expression ? expression : assignment-expression
It's used as;
condition ? condition_is_true_expression : condition_is_false_expression
That is, if condition evaluates to true, the expression evaluates to condition_is_true_expression otherwise the expression evaluates to condition_is_false_expression.
So in your case, result would always be assigned the value 1.
Note 1; A common mistake that one makes while working with the conditional operator, is to forget that it has a fairly low operator precedence.
Note 2; Some functional languages doesn't provide this operator, as they have expression 'if...else' constructs, such as OCaml;
let value = if b then 1 else 2
Note 3; A funny use case, which is perfectly valid is using the conditional operator, to decide, which of two variable to assign a value to.
(condition ? x : y) = 1;
Notice the parentheses are necessary, as this is really what you get without them;
condition ? x : (y = 1);
They are called shorthand if-else or ternary operators.
See this article for more information.