Variable definition in C - c

What does following declaration mean in C?
char a = (10,23,21);
While printing the value of "a" with "%u" the output is 21.
gcc is not giving any error.
What's this kinda declaration and what's the use of it?

You are seeing the comma operator at work. The comma operator a,b evaluates a, throws away the result, then returns b.
Since 10 and 23 have no side effects, this is equivalent to char a = 21;

This is a use of the scalar comma operator. The comma operator evaluates each expression on the left side and throws away the return value, finally returning the rightmost value.
In this case, it's useless; however, if you use it with expressions with side-effects, then it has a real effect.
Example of a semi-"useful" expression (with side-effects):
int a = 10;
int is_a_odd_after_increment = ++a, a % 2;
The first expression (++a) has a clear side-effect, and it is evaluated first (before the a % 2). The second expression is the expression that is yielded into the assignment.

Related

How is the increment operator evaluated in C programs?

I have two expressions:
int a=5;
int c=++a;// c=6, a=6
int b=a++;// b=6, a=7
In the second instruction, the increment is evaluated first and in the third instruction, the increment is evaluated after the assignment.
I know that the increment operator has a higher priority. Can anyone explain to me why it's evaluated after assignment in the third expression?
The result is not related to the order of operations but to the definition of prefix ++ and postfix ++.
The expression ++a evaluates to the incremented value of a. In contrast, the expression a++ evaluates to the current value of a, and a is incremented as a side effect.
Section 6.5.2.4p2 of the C standard says the following about postfix ++:
The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).
And section 6.5.3.1p2 says the following about prefix ++:
The value of the operand of the prefix ++ operator is incremented. The
result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1)
++a and a++ are simply different operators, despite the same symbol ++. One is prefix-increment, one is postfix-increment. This has nothing to do with priority compared to assignment. (just like a - b and -a are different operators despite the same symbol -.)
EDIT: It was pointed out that this is about C and not C++... oops. So, the following explanation may be confusing if you only know C; all you need to know is that int& is a reference to an int, so it's like having a pointer but without the need to dereference it, so modifying a inside of these functions actually modifies the variable you passed into the functions.
You could imagine them like functions:
int prefixIncrement(int& a) {
return ++a;
}
...is the same as:
int prefixIncrement(int& a) {
a += 1;
return a;
}
And:
int postfixIncrement(int& a) {
return a++;
}
...is the same as:
int postfixIncrement(int& a) {
int old = a;
a += 1;
return old;
}
For nitpickers: Yes, actually we'd need move semantics on the return value for postfixIncrement.

Value Assignment in C

I came across this question and expected it to show up as a compile time error but to my surprise each statement separated by comma is executed and the final value is assigned to the variable.
int a,b=5;
a=(b++,++b,b*4,b-3);
printf("%d",a);
Output is 4
This output is exactly what should be the printed when each of those comma separated statements are executed separately. What I am not understanding is how and why does C allow this and how does compiler process this.
See What does the comma operator , do?
After understanding how the comma operator works, we can tell that this code is equivalent to:
int a,b=5;
b++;
++b;
b*4; // nonsense, the result isn't stored anywhere
a=b-3;
printf("%d",a);
5 + 1 + 1 - 3 = 4. The b*4 part does nothing and is just obfuscation.
comma acts both as a separator (in declaration of variables) and operator (evaluation of expressions).
In this case, comma acts as an operator. The comma operator introduces a sequence point between expressions.
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.
So your code is:
a = (b++, ++b, b*4, b-3);
Which is as if you had written this:
a = (5, 7, 28, 4);
So a is 4.

On Dev C++ compiler the output of the following code is 10,10 I am not able to understand how the value of a is assigned to b?

#include<stdio.h>
int main()
{
int a=10,b=20;
a,b=(b,a);
printf("%d, %d ",a,b);
return 0;
}
Output of the following code on dev cpp is 10, 10 I am not getting why?
The comma operator separates expressions in a way similar to how the semicolon separates statements. The value of a comma expression is the same as the value of the last expression in the chain.
Your code snippet has two comma operators - one on the left and one on the right side of the assignment operator. The right side selects the value to be assigned - the last one in the chain, i.e. a. Since comma has lowest priority, assignment is parsed done to variable b, i.e. the assignment is equivalent to
b = a;
Expression a on the left side of the assignment operator has no effect, because it reads the value of a without making any changes to it.
The comma operator works like that. Your statements are:
a // no op
b = (b, // no op
a)
and the value of (b,a) is the value of the last expression in the sequence of comma separated expressions, i.e. a, which is equal to 10.
Try this also:
printf("%d\n", (3,7));

Assigning multiple integers separated by comma to an int in C - Why does that work? What for? [duplicate]

This question already has answers here:
C comma operator
(4 answers)
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I saw this in an exam and when I tried it out I was surprised. I tried it online and it works too. So I think it is the C language.
Why is that working? What is the use case for such an assignment syntax?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int i = (1,2,3,4,5);
printf("%d", i);
return 0;
}
These are not "multiple integers", but a comma operator. The whole parenthesised part is a single expression with each sub-expression (separated by commas) evaluated strictly from left to right. The results of all but the rightmost subexpression are ignored. The result of the whole expression is that of the last (rightmost) expression. Here it is the integer value 5.
Note that this operator is mostly used where only a single expression is allowed to add further side-effects. E.g. in a loop like:
int cnt = 0;
for ( const char *cp = "Hello" ; *cp != '\0' ; cp++, cnt++ ) ;
This counts the number of characters in a C-string, incrementing the pointer and cnt after each iteration. The results are ignored here.
So, this is in no way related to tuples or similar like in Python. There are actually no cases the usage of this operator is unavoidable and it should be used with caution — and some coding standards forbid its usage.
That's the comma operator at work. It evaluates the expression on its left-hand side, creates a sequence point, discards the value of the expression, then evaluates the expression on the right-hand side, and returns that as the value. When there are multiple expressions as in the example, then each is evaluated in turn and only the last is kept. With the sample, the compiler does the evaluation because every value is known at compile time. Note that the argument list to a function is not a use of the comma operator.
That isn't a valid use-case for the comma operator. What might be a more nearly valid use-case would be some operations with side-effects (such as function calls) that need to be sequenced and the final value assigned:
int i = (getchar(), getchar(), getchar());
This sets i to the third character in standard input, or EOF if there are not three characters left in the standard input to be read. Still not a realistic use-case, but better than assigning a list of constants.
In addition to the other answers, you need to watch for instances where a , is the comma operator as opposed to when it is a separator. For example, the following is invalid:
int i = 1,2,3,4,5;
In this case, the , is a separator between variable declarations. It declares i as an int and initializes it to 1, then it attempts to parse 2 as a variable name, which fails.
It works because you're using the "comma operator", which evaluates the subexpressions on the left and right, and has the value from the right-hand expression.
So in (1,2,3,4,5), 1 is evaluated and the result is discarded, then 2,3,4,5... in which (because of the next comma) 2 is evaluated and the result discarded, then 3,4,5... in which 3 is evaluated and discarded, then 4,5... in which 4 is evaluated and discarded, then 5 which becomes the result of the expression.
As for when it's useful, mainly as a shortcut when you need to evaluate several (sub)expressions for their side effects but aren't interested in their values (except maybe the last one). It's sometimes convenient in for loop expressions, such as when incrementing two variables:
for (i=0,j=1; j < len; i++,j++) {
..where it appears in both the initialization expression and the loop expression.
Why is that working?
Because its a valid C syntax. The comma in (1,2,3,4,5) are comma operator
C11: 6.5.17 Comma operator
Syntax
1 expression:
assignment-expression
expression , assignment-expression
Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.114)
What is the use case for such an assignment syntax?
See the example below
3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.

Assignment of a parenthesized expression

Consider the following snippet:
int a, b, c;
a = (b = 3, c = 4, 5, 6);
It turns out that, after those lines are executed, b has the value 3, c has the value 4. Nothing unexpected so far. But a has value 6. Why is that?
Also, does this have an useful use?
Because the , operator discards all the operands to the left, and since 6 is the rightmost operand, it's the only one which is not discarded.
This is from § 6.5.17 n1570 draft
The left operand of a comma operator is evaluated as a void expression; there is a
sequence point between its evaluation and that of the right operand. Then the right
operand is evaluated; the result has its type and value.
EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot
appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists
of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.
You can read more here
Whenever you use a separator (i.e. ',') in an assignment statement, it assigns a value that is in the last. For example
int i = (2,3);
// i = 3;
variable i get the value of 3 not 2.

Resources