C: Only compiles if assigned after declaration - c

This gives compilation error.
int main(void)
{
int a = 1, 2, 3;
printf("%d", a);
return 0;
}
But,
int main(void)
{
int a;
a = 1, 2, 3;
printf("%d", a);
return 0;
}
prints 1. Why? I have no idea why this happens.

In your first code, comma is used as a separator.
In your second code, it's used as operator.
So, the first code is simply gives error.
In the precedence table, comma operator has the least precedence. So, in the second program,
a = 1, 2, 3
is equivalent to
(a = 1), 2, 3
As, a=1, 1 is printed.
The Wiki article for this one is just fine.

Ah the comma oprator :).
In C, the comma is an operator just like +, - * and /. This means it obeys rules of precendence, and it has a very low precedence (the lowest, in fact). Given that is has a lower precedence than the assignment operator, it is evaluated after any assignments in the same expression. When you type:
a = 1, 2, 3;
It evaluates the assignment, a = 1, and then the comma(s). This is equivalent to writing:
(a = 1), 2, 3;
If you were to place brackets in your code, the value assigned to a would differ would differ:
a = (1, 2, 3); // a now equals 3.
This is because the comma operator discards the left hand argument, and results in the right hand argument. So in this case, 1,2 evaluates to 2, and 2,3 evalues to 3.
The first example fails to compile because C supports the following syntax:
int a = 1, b = 2, c = 3;
Which declares 3 variables a, b and c, assigning values 1, 2 and 3, respectively. The combination of the = and , operators is confusing, hence why what you've written causes a compiler error. If you were to rewrite your assignment as follows:
int a = (1, 2, 3);
It clarifies the order of operations, and assigns the value 3 to a.
Here's a table showing operator precedence in C.

In the first line:
int a = 1, 2, 3;
you are attempting to declare variables 2 and 3 of type int, which i'n't allowed.
int a = 1, b, c; // OK
int a = 1, b = 2, c = 3; // OK
int a = (1, 2, 3); // OK - a == 3
In the second line:
a = 1, 2, 3;
you're using a comma operator; a is assigned 1 (not 3 as I first wrote; comma has the lowest of all operator precedences - and the 2 and 3 are thrown away).

As part of a declaration, a comma means that another declaration (of the same type) follows.
In your second example , it's the comma operator, which has very low precedence. It's equivalent to
(a = 1), 2, 3;

Because the standard says so:
(6.7) declaration:
declaration-specifiers init-declarator-listopt ;
(6.7) declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
(6.7) init-declarator-list:
init-declarator
init-declarator-list , init-declarator
(6.7) init-declarator:
declarator
declarator = initializer
(6.7.8) initializer:
assignment-expression
(6.5.16) assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
(6.5.17) expression:
assignment-expression
expression , assignment-expression
In the initializer (6.7) the comma is a separator. In the expression (6.5.17) the comma is an operator.

Related

Comma operator in c [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 5 years ago.
#include<stdio.h>
int main(void) {
int a;
a = (1, 2), 3;
printf("%d", a);
return 0;
}
output: 2
Can any one explain how output is 2?
Can any one explain how output is 2?
Because the precedence of the assignment operator (=) is higher than the comma operator (,).
Therefore, the statement:
a = (1, 2), 3;
is equivalent to:
(a = (1, 2)), 3;
and the expression (1, 2) evaluates to 2.
Can any one explain how output is 2?
In the statement
a = (1, 2), 3;
, used is a comma operator.
Due to higher operator precedence of = operator than that of , operator, the expression operand (1, 2) will bind to = as
(a = (1, 2)), 3;
In case of comma operator, the left operand of a comma operator is evaluated to a void expression, then the right operand is evaluated and the result has the value and type of the right operand.
There are two comma operators here. For the first comma operator in the expression (1, 2), 1 will be evaluated to void expression and then 2 will be evaluated and will be assigned to a.
Now side effect to a has been taken place and therefore the right operand of second comma operator 3 will be evaluated and the value of the expression (a = (1, 2)), 3 will be 3.
the result of:
a = x, y => x
a = (i, j) => j
therefore, if we have:
x = (1 , 2)
a = (1 , 2) , 3 => 2
As said here:
The comma operator separates expressions (which have value) in a way
analogous to how the semicolon terminates statements, and sequences of
expressions are enclosed in parentheses analogously to how sequences
of statements are enclosed in braces: (a, b, c) is a sequence of
expressions, separated by commas, which evaluates to the last
expression c while {a; b; c;} is a sequence of statements, and does
not evaluate to any value. A comma can only occur between two
expressions – commas separate expressions – unlike the semicolon,
which occurs at the end of a (non-block) statement – semicolons
terminate statements.
The comma operator has the lowest precedence of any C operator, and
acts as a sequence point. In a combination of commas and semicolons,
semicolons have lower precedence than commas, as semicolons separate
statements but commas occur within statements, which accords with
their use as ordinary punctuation: a, b; c, d is grouped as (a, b);
(c, d) because these are two separate statements.
I hope this answers your question.

a=3,2,1; gives error in gcc

I tried the following code in gcc:
#include<stdio.h>
int main()
{
int a=3,2,1;//////////////////////ERROR!//////////////////////////
printf("%d", a);
return 0;
}
I expected it to compile successfully as:
a series of integer expressions seperated by commas will be evaluated from left to right and the value of the right-most expression becomes the value of the total comma separated expression.
Then, the value of the integer variable a should have been 1 right? Or is it 3?
And why am I getting this error when I try to execute this program?
error: expected identifier or '(' before numeric constant
That's parsed as a three-part variable declaration, with two invalid variables.
You need to wrap the entire initializer in parentheses so that it's parsed as a single expression:
int a=(3,2,1);
If you separate the initialization from the declaration, you may get what you expected:
int a;
a = 3, 2, 1; // a == 3, see note bellow
or
int a;
a = (3, 2, 1); // a == 1, the rightmost operand of 3, 2, 1
as your original command is syntactically incorrect (it is the declaration so it expected other variables to declare instead of numbers 2 and 1)
Note: All side effects from the evaluation of the left-operand are completed before beginning the evaluation of the right operand.
So
a = 3, 2, 1
which are 3 comma operators a = 3, 2 and 1 are evaluated from left to right, so the first evaluation is
a = 3, 2
which result 2 (right-operand) (which is by the way not assigned to any variable, as the value of the left-operand a = 3 is simply 3), but before giving this result it is completed the side effect a = 3 of the left-operand, i. e. assigning 3 to variable a. (Thank AnT for his observation.)

How will be operands inside (a += 3, 5, a) are going to dealt or caculated in order to print the value of "a"?

The code snippet is:
int main()
{
int a = 1, b = 2, c = 3;
printf("%d", a += (a += 3, 5, a));
}
Though it displays 8 in the terminal as an output. But am not getting the concept behind it.
The expression a += (a += 3, 5, a) will invoke undefined behavior.
C standard says
C11: 6.5.16 Assignment operators (p3):
[...] The side effect of updating the stored value of the left operand is
sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
It is not guaranteed that whether the left most a will be evaluated before or after the evaluation of (a += 3, 5, a). That will result in undefined behavior.
This is an effect how the comma operator works, the last element is the one that is used as the value of the statement. So essentially what you got here is the following:
a += (a += 3, 5, a)
This evaluates a+=3 first, this makes a=4 this result is discarded, then evaluate 5 then this result is discarded, then evaluate a and keep this as it's the last item. The result from (a += 3, 5, a) is the last item which is a which is 4.
Then you get
a += 4
so a is 8.
Important Note: that this is an artifact of how your compiler has generated the code. The C standard doesn't guarantee the order of execution for the assignment to a in this situation. See haccks answer for more information about that.
As we know that comma has lowest precedence as operator so in,
a + = (a + = 3, 5, a) in this what will happen is first evaluation will be like this a+3 = 4 but then it will be discarded now evalutation will be a+5 = 6 now in third step we have to do a+a right
so here answer will be value from previous operation i.e. 6 and then
6+1 = 7 now we will come out of the brackets and we will do a = a+ 7 which is
a = 1 + 7 so answer will be 8
so therefore (a += 3,5,a) will get you 7 and a = a + 7 will get you 8 which will be printed finally

comma separated assignment to an integer variable n c [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I'm unable to understand the working of this piece of code.
#include<stdio.h>
void main(){
int a,b;
a=3,1;
b=(5,4);
printf("%d",a+b);
}
The output is 7. What is that assignment?
Comma operator evaluates its first operand and discards the result, and then evaluates the second operand and returns this value.
After executing
a=3,1; // (a = 3), 1;
a will have 3 and after
b=(5,4); // Discard 5 and the value of the expression (5,4) will be 4
b will have 4.
Some more examples on Wikipedia:
// Examples: Descriptions: Values after line is evaluated:
int a=1, b=2, c=3, i=0; // commas act as separators in this line, not as an operator
// ... a=1, b=2, c=3, i=0
i = (a, b); // stores b into i
// ... a=1, b=2, c=3, i=2
i = a, b; // stores a into i. Equivalent to (i = a), b;
// ... a=1, b=2, c=3, i=1
i = (a += 2, a + b); // increases a by 2, then stores a+b = 3+2 into i
// ... a=3, b=2, c=3, i=5
i = a += 2, a + b; // increases a by 2, then stores a to i, and discards unused
// a + b rvalue. Equivalent to (i = (a += 2)), a + b;
// ... a=5, b=2, c=3, i=5
i = a, b, c; // stores a into i, discarding the unused b and c rvalues
// ... a=5, b=2, c=3, i=5
i = (a, b, c); // stores c into i, discarding the unused a and b rvalues
// ... a=5, b=2, c=3, i=3
return a=4, b=5, c=6; // returns 6, not 4, since comma operator sequence points
// following the keyword 'return' are considered a single
// expression evaluating to rvalue of final subexpression c=6
return 1, 2, 3; // returns 3, not 1, for same reason as previous example
return(1), 2, 3; // returns 3, not 1, still for same reason as above. This
// example works as it does because return is a keyword, not
// a function call. Even though most compilers will allow for
// the construct return(value), the parentheses are syntactic
// sugar that get stripped out without syntactic analysis
a=3,1; // (a=3),1 -- value of expression is 1, side effect is changing a to 3
b=(5,4);
printf("%d",a+b); // 3 + 4
In this statement
a=3,1;
two operators are used: the assignment operator and the comma operator. The priority of the assignment operator is greater than the priority of the comma operator, thus this statement is equivalent to
( a = 3 ), 1;
1 is simply discarded, so a is assigned the value 3.
In this statement
b=(5,4);
due to the parentheses the comma operator is evaluated first. Its value is the value of the last expression, 4. So b is assigned the value 4.
As result you get a + b => 3 + 4 which equals 7.

Using comma operator in c

I have read that comma operator is used to assign expression, and the right expression is supplied to lvalue.
But why does this program assign left expression to lvalue when not using parenthesis? I am using turbo c compiler.
int b=2;
int a;
a=(b+2,b*5); // prints 10 as expected
a=b+2,b*5; // prints 4 when not using parenthesis
Also the following works:
int a =(b+2,b*5);
But this generates an error:
int a =b+2,b*5; // Error
I can't understand why.
Because precedence of , operator is lower than of = one, this...
a=b+2,b*5;
... will actually be evaluated as...
a = b + 2;
b * 5;
With int i = b + 2, b * 5; is a bit different, because comma has different meaning in declaration statements, separating different declarations from each other. Consider this:
int a = 3, b = 4;
You still have comma here, but now it separates two variable assignment-on-declarations. And that's how the compiler attempts to treat that line from your example - but fails to get any meaning from b * 5 line (it's neither assignment nor declaration).
Now, int a = (b + 2, b * 5) is different: you assign a value of b + 2, b * 5 expression to a variable a of type int. The first sub-expression is discarded, leaving you just with b * 5.

Resources