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

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.

Related

Evaluation order in ternary operator with increments

#define MAX(a,b) ((a)>(b) ? (a) : (b))
int main(void) {
int a=2;
int b=3;
int c = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a);// a=3
printf("\nb= %d", b);//b=5
printf("\nc= %d", c);//c=4
a=3;
b=2;
cc = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a); // a=5
printf("\nb= %d", b); //b=3
printf("\nc= %d", c); //c=4
return 0;
}
I would like to know why c is not evaluating to 5.
It appears to me the evaluation order should be:
First both a and be get incremented in (a++)>(b++)
If for example the first one is greater, the ternary operator in
c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a
increments again.
The result of the ternary expression, which is a twice-increment,
should be assigned to c, then c should have the greater value
twice-incremented, that is 5. However, I am getting 4. I suspect the
greater value's second increment is happening at the end, but I can't
explain why, since the parentheses seem to indicate that the
assignment comes at the end.
Any idea?
The postfix ++ operator has a result and a side effect. The result of a++ is the value of a before the increment - given
int a = 1;
int x = a++;
the value of x will be 1 and the value of a will be 2. Note that the side effect of adding 1 to a does not have to be applied immediately after evaluation - it only has to be applied before the next sequence point.
So, looking at
((a++) > (b++)) ? (a++) : (b++)
The ?: operator forces left-to-right evaluation, so the first thing that happens is that (a++) > (b++) is evaluated1. Since a is initially 2 and b is initially 3, the result of the expression is false (0). The ? operator introduces a sequence point, so the side effects to a and b are applied and a is now 3 and b is now 4.
Since the result of the condition expression was 0, we evaluate b++. Same thing, the result of the expression is the current value of b (4), and that value gets assigned to c. The side effect to b is applied at some point, and by the time everything's finished, a is 3, b is 5, and c is 4.
Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.
Let's consider for example this declaration
int c = MAX(a++,b++);
after the macro substitution there will be
int c = (( a++) >( b++ ) ? (a++) : (b++));
The variables a and b are initialized like
int a=2;
int b=3;
As a is less than b then the third expression (b++) will be evaluated as a result of the conditional operator. In the first expression ( a++) >( b++ ) a and b were incremented. There is a sequence point after the evaluation of the first expression.
So a will be set to 3, b will be set to 4.
As it was already said the value of the conditional operator is the value of the third expression (b++) where there is used the post-increment. The value of the post-increment operator is the value of its operand before incrementing.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 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).
So the value of the conditional operator is 4. This value will be assigned to the variable c. But as a side effect the value of b will be incremented.
Thus after this declaration a will be equal to 3, b will be equal to 5 and c will be equal to 4.
For clarity this declaration
int c = (( a++) >( b++ ) ? (a++) : (b++));
in fact can be rewritten in the logically equivalent way.
int result = a > b;
++a;
++b;
int c;
if ( result != 0 )
{
c = a++;
}
else
{
c = b++;
}
For a++ it's equivalent as saying
int temp = a;
a = a + 1;
return temp;
so in the case of a=2, b=3, we can go to the condition (a++)>(b++) and we can have a rewritten as
int temp1 = a;
a = a + 1;
return temp1;
and b rewritten as
int temp2 = b;
b = b + 1;
return temp2;
now since it's only a conditional statement, we're really just evaluating the old values of a and b before the increment which is temp1 = 2 and temp2 = 3 while at the same time a and b values have changed a = 3, b = 4. Since temp1 < temp2 from the old value, we go to the false clause of the ternary operator (b++) and do the same thing as we did before
int temp3 = b;
b = b + 1;
return temp3;
so now b is 5 while the returned temp3 is the previous value of b which is 4. Hope this helps!

Understand comma operator

int main()
{
int a = (1,2,3);
int b = (++a, ++a, ++a);
int c= (b++, b++, b++);
printf("%d %d %d", a,b,c);
}
I am beginner in programming. I am not getting how does this program shows me output of 6 9 8.
The , used in all the three declarations
int a = (1,2,3);
int b = (++a, ++a, ++a);
int c = (b++, b++, b++);
are comma operator. It evaluates the first operand1 and discard it, then evaluates the second operand and return its value. Therefore,
int a = ((1,2), 3); // a is initialized with 3.
int b = ((++a, ++a), ++a); // b is initialized with 4+1+1 = 6.
// a is 6 by the end of the statement
int c = ((b++, b++), b++); // c is initialized with 6+1+1 = 8
// b is 9 by the end of the statement.
1 Order of evaluation is guaranteed from left to right in case of comma operator.
The code is not in any way good and nobody in their right mind would ever write it. You should not spend any time in looking at that kind of code, but I will still give an explanation.
The comma operator , means "do the left one, discard any result, do the right one and return the result. Putting the parts in parentheses doesn't have any effect on the functionality.
Written more clearly the code would be:
int a, b, c;
a = 3; // 1 and 2 have no meaning whatsoever
a++;
a++;
a++;
b = a;
b++;
b++;
c = b;
b++;
The pre- and post-increment operators have a difference in how they act and that causes the difference in values of b and c.
I am beginner in programming. I am not getting how does this program
shows me output of
Just understand comma operators and prefix ,postfix .
according to rules mentioned in links given to you
int a = (1,2,3); // a is initialized with 3 last argument .
int b = (++a, ++a, ++a); // a is incremented three time so becomes 6 and b initilized with 6 .
int c = (b++, b++, b++); // b incremented two times becomes 8 and c initialized with 8.
// b incremented once more time becomes 9

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.

C: Only compiles if assigned after declaration

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.

What is a comma separated set of assignments?

I noticed in a routine
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
Why does it work?
What does it do?
A comma operator is a sequence point : each comma separated expression are evaluated from left to right. The result has the type and value of the right operand. Functionally, your example is equivalent to (the much more readable ?) :
else
{
*pbuf++ = '%';
*pbuf++ = to_hex(*pstr >> 4);
*pbuf++ = to_hex(*pstr & 15);
}
Here is another example that the standard provides for the comma operator (6.5.17) :
In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the
second of which has the value 5.
From Wikipedia:
In the C and C++ programming languages, the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type). The comma operator has the lowest precedence of any C operator, and acts as a sequence point.
The use of the comma token as an operator is distinct from its use in function calls and definitions, variable declarations, enum declarations, and similar constructs, where it acts as a separator.
In this example, the differing behavior between the second and third lines is due to the comma operator having lower precedence than assignment.
int a=1, b=2, c=3, i; // comma acts as separator in this line, not as an operator
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 = 5 into i ... a=5, b=2, c=3, i=5
i = a, b, c; // stores a into i ... a=5, b=2, c=3, i=5
i = (a, b, c); // stores c into i ... a=5, b=2, c=3, i=3
Link: http://en.wikipedia.org/wiki/Comma_operator
Why it shouldn't work? It sets %, to_hex(*pstr >> 4), to_hex(*pstr & 15) to sequential memory block addressed by pbuf. The equivalent code may be the following:
else {
*pbuf = '%';
*(pbuf + 1) = to_hex(*pstr >> 4);
*(pbuf + 2) = to_hex(*pstr & 15);
pbuf += 3;
}

Resources