Two Equal Signs in One Line? - c

Could someone please explain what this does and how it is legal C code? I found this line in this code: http://code.google.com/p/compression-code/downloads/list, which is a C implementation of the Vitter algorithm for Adaptive Huffman Coding
ArcChar = ArcBit = 0;
From the function:
void arc_put1 (unsigned bit)
{
ArcChar <<= 1;
if( bit )
ArcChar |= 1;
if( ++ArcBit < 8 )
return;
putc (ArcChar, Out);
ArcChar = ArcBit = 0;
}
ArcChar is an int and ArcBit is an unsigned char

The value of the expression (a = b) is the value of b, so you can chain them this way. They are also right-associative, so it all works out.
Essentially
ArcChar = ArcBit = 0;
is (approximately1) the same as
ArcBit = 0;
ArcChar = 0;
since the value of the first assigment is the assigned value, thus 0.
Regarding the types, even though ArcBit is an unsigned char the result of the assignment will get widened to int.
1   It's not exactly the same, though, as R.. points out in a comment below.

ArcChar = ArcBit = 0;
The assignment is left-associative, so it's equivalent to:
ArcChar = (ArcBit = 0);
The result of ArcBit = 0 is the newly-assined value, that is - 0, so it makes sense to assign that 0 to ArcChar

It sets both variables to zero.
int i, j;
i = j = 0;
The same as writing
int i, j;
j = 0;
i = j;
or writing
int i, j;
i = 0;
j = 0;

That is just chaining of the assignment operator. The standard says in 6.5.16 Assignment operators:
An assignment operator shall have a modifiable lvalue as its left operand.
An assignment operator stores a value in the object designated by the left operand. An
assignment expression has the value of the left operand after the assignment, but is not an
lvalue. The type of an assignment expression is the type of the left operand unless the
left operand has qualified type, in which case it is the unqualified version of the type of
the left operand. The side effect of updating the stored value of the left operand shall
occur between the previous and the next sequence point.
So you may do something like:
a=b=2; // ok
But not this:
a=2=b; // error

An assignment operation (a = b) itself returns an rvalue, which can be further assigned to another lvalue; c = (a = b). In the end, both a and c will have the value of b.

It assigns ArcBit to 0, then assigns ArcChar to the value of the expression ArcBit = 0 (ie. 0)

In some languages, assignments are statements: they cause some action to take place, but they don't have a value themselves. For example, in Python1 it's forbidden to write
x = (y = 10) + 5
because the assignment y = 10 can't be used where a value is expected.
However, C is one of many languages where assignments are expressions: they produce a value, as well as any other effects they might have. Their value is the value that is being assigned. The above line of code would be legal in C.
The use of two equals signs on one line is interpreted like this:
ArcChar = (ArcBit = 0);
That is: ArcChar is beging assigned the value of ArcBit = 0, which is 0, so both variables end up being 0.
1 x = y = 0 is actually legal in Python, but it's considered a special-case of the assignment statement, and trying to do anything more complicated with assignments will fail.

Assignment in C is an expression, not statement. Also you can freely assign values of different size (unsigned char to int and vice versa). Welcome to C programming language :)

You can do this:
http://en.wikibooks.org/wiki/C_Programming/Variables
Moreover,
[a int] = 0; is possible.
[a char] = 0; is possible too.
arcbit and arcchar equals 0.

As Hasturkun said, this is due to operator associativity order
C Operator Precedence and Associativity

Related

How is this working in c language. Output is 1 and 2 respectively. But how? [duplicate]

What does the , operator do in C?
The expression:
(expression1, expression2)
First expression1 is evaluated, then expression2 is evaluated, and the value of expression2 is returned for the whole expression.
I've seen used most in while loops:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
It will do the operation, then do a test based on a side-effect. The other way would be to do it like this:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
The comma operator will evaluate the left operand, discard the result and then evaluate the right operand and that will be the result. The idiomatic use as noted in the link is when initializing the variables used in a for loop, and it gives the following example:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Otherwise there are not many great uses of the comma operator, although it is easy to abuse to generate code that is hard to read and maintain.
From the draft C99 standard the grammar is as follows:
expression:
assignment-expression
expression , assignment-expression
and paragraph 2 says:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. 97) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
Footnote 97 says:
A comma operator does not yield an lvalue.
which means you can not assign to the result of the comma operator.
It is important to note that the comma operator has the lowest precedence and therefore there are cases where using () can make a big difference, for example:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
will have the following output:
1 4
The comma operator combines the two expressions either side of it into one, evaluating them both in left-to-right order. The value of the right-hand side is returned as the value of the whole expression.
(expr1, expr2) is like { expr1; expr2; } but you can use the result of expr2 in a function call or assignment.
It is often seen in for loops to initialise or maintain multiple variables like this:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Apart from this, I've only used it "in anger" in one other case, when wrapping up two operations that should always go together in a macro. We had code that copied various binary values into a byte buffer for sending on a network, and a pointer maintained where we had got up to:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Where the values were shorts or ints we did this:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Later we read that this was not really valid C, because (short *)ptr is no longer an l-value and can't be incremented, although our compiler at the time didn't mind. To fix this, we split the expression in two:
*(short *)ptr = short_value;
ptr += sizeof(short);
However, this approach relied on all developers remembering to put both statements in all the time. We wanted a function where you could pass in the output pointer, the value and and the value's type. This being C, not C++ with templates, we couldn't have a function take an arbitrary type, so we settled on a macro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
By using the comma operator we were able to use this in expressions or as statements as we wished:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
I'm not suggesting any of these examples are good style! Indeed, I seem to remember Steve McConnell's Code Complete advising against even using comma operators in a for loop: for readability and maintainability, the loop should be controlled by only one variable, and the expressions in the for line itself should only contain loop-control code, not other extra bits of initialisation or loop maintenance.
It causes the evaluation of multiple statements, but uses only the last one as a resulting value (rvalue, I think).
So...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
should result in x being set to 8.
As earlier answers have stated it evaluates all statements but uses the last one as the value of the expression. Personally I've only found it useful in loop expressions:
for (tmp=0, i = MAX; i > 0; i--)
The only place I've seen it being useful is when you write a funky loop where you want to do multiple things in one of the expressions (probably the init expression or loop expression. Something like:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Pardon me if there are any syntax errors or if I mixed in anything that's not strict C. I'm not arguing that the , operator is good form, but that's what you could use it for. In the case above I'd probably use a while loop instead so the multiple expressions on init and loop would be more obvious. (And I'd initialize i1 and i2 inline instead of declaring and then initializing.... blah blah blah.)
I'm reviving this simply to address questions from #Rajesh and #JeffMercado which i think are very important since this is one of the top search engine hits.
Take the following snippet of code for example
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
It will print
1 5
The i case is handled as explained by most answers. All expressions are evaluated in left-to-right order but only the last one is assigned to i. The result of the ( expression )is1`.
The j case follows different precedence rules since , has the lowest operator precedence. Because of those rules, the compiler sees assignment-expression, constant, constant .... The expressions are again evaluated in left-to-right order and their side-effects stay visible, therefore, j is 5 as a result of j = 5.
Interstingly, int j = 5,4,3,2,1; is not allowed by the language spec. An initializer expects an assignment-expression so a direct , operator is not allowed.
Hope this helps.

int a = (2, 3, 4, 5); & int a = {2, 3, 4, 5}; How these statements are working in C/C++? [duplicate]

What does the , operator do in C?
The expression:
(expression1, expression2)
First expression1 is evaluated, then expression2 is evaluated, and the value of expression2 is returned for the whole expression.
I've seen used most in while loops:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
It will do the operation, then do a test based on a side-effect. The other way would be to do it like this:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
The comma operator will evaluate the left operand, discard the result and then evaluate the right operand and that will be the result. The idiomatic use as noted in the link is when initializing the variables used in a for loop, and it gives the following example:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Otherwise there are not many great uses of the comma operator, although it is easy to abuse to generate code that is hard to read and maintain.
From the draft C99 standard the grammar is as follows:
expression:
assignment-expression
expression , assignment-expression
and paragraph 2 says:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. 97) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
Footnote 97 says:
A comma operator does not yield an lvalue.
which means you can not assign to the result of the comma operator.
It is important to note that the comma operator has the lowest precedence and therefore there are cases where using () can make a big difference, for example:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
will have the following output:
1 4
The comma operator combines the two expressions either side of it into one, evaluating them both in left-to-right order. The value of the right-hand side is returned as the value of the whole expression.
(expr1, expr2) is like { expr1; expr2; } but you can use the result of expr2 in a function call or assignment.
It is often seen in for loops to initialise or maintain multiple variables like this:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Apart from this, I've only used it "in anger" in one other case, when wrapping up two operations that should always go together in a macro. We had code that copied various binary values into a byte buffer for sending on a network, and a pointer maintained where we had got up to:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Where the values were shorts or ints we did this:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Later we read that this was not really valid C, because (short *)ptr is no longer an l-value and can't be incremented, although our compiler at the time didn't mind. To fix this, we split the expression in two:
*(short *)ptr = short_value;
ptr += sizeof(short);
However, this approach relied on all developers remembering to put both statements in all the time. We wanted a function where you could pass in the output pointer, the value and and the value's type. This being C, not C++ with templates, we couldn't have a function take an arbitrary type, so we settled on a macro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
By using the comma operator we were able to use this in expressions or as statements as we wished:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
I'm not suggesting any of these examples are good style! Indeed, I seem to remember Steve McConnell's Code Complete advising against even using comma operators in a for loop: for readability and maintainability, the loop should be controlled by only one variable, and the expressions in the for line itself should only contain loop-control code, not other extra bits of initialisation or loop maintenance.
It causes the evaluation of multiple statements, but uses only the last one as a resulting value (rvalue, I think).
So...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
should result in x being set to 8.
As earlier answers have stated it evaluates all statements but uses the last one as the value of the expression. Personally I've only found it useful in loop expressions:
for (tmp=0, i = MAX; i > 0; i--)
The only place I've seen it being useful is when you write a funky loop where you want to do multiple things in one of the expressions (probably the init expression or loop expression. Something like:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Pardon me if there are any syntax errors or if I mixed in anything that's not strict C. I'm not arguing that the , operator is good form, but that's what you could use it for. In the case above I'd probably use a while loop instead so the multiple expressions on init and loop would be more obvious. (And I'd initialize i1 and i2 inline instead of declaring and then initializing.... blah blah blah.)
I'm reviving this simply to address questions from #Rajesh and #JeffMercado which i think are very important since this is one of the top search engine hits.
Take the following snippet of code for example
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
It will print
1 5
The i case is handled as explained by most answers. All expressions are evaluated in left-to-right order but only the last one is assigned to i. The result of the ( expression )is1`.
The j case follows different precedence rules since , has the lowest operator precedence. Because of those rules, the compiler sees assignment-expression, constant, constant .... The expressions are again evaluated in left-to-right order and their side-effects stay visible, therefore, j is 5 as a result of j = 5.
Interstingly, int j = 5,4,3,2,1; is not allowed by the language spec. An initializer expects an assignment-expression so a direct , operator is not allowed.
Hope this helps.

What's this operator in C? [duplicate]

What does the , operator do in C?
The expression:
(expression1, expression2)
First expression1 is evaluated, then expression2 is evaluated, and the value of expression2 is returned for the whole expression.
I've seen used most in while loops:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
It will do the operation, then do a test based on a side-effect. The other way would be to do it like this:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
The comma operator will evaluate the left operand, discard the result and then evaluate the right operand and that will be the result. The idiomatic use as noted in the link is when initializing the variables used in a for loop, and it gives the following example:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Otherwise there are not many great uses of the comma operator, although it is easy to abuse to generate code that is hard to read and maintain.
From the draft C99 standard the grammar is as follows:
expression:
assignment-expression
expression , assignment-expression
and paragraph 2 says:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. 97) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
Footnote 97 says:
A comma operator does not yield an lvalue.
which means you can not assign to the result of the comma operator.
It is important to note that the comma operator has the lowest precedence and therefore there are cases where using () can make a big difference, for example:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
will have the following output:
1 4
The comma operator combines the two expressions either side of it into one, evaluating them both in left-to-right order. The value of the right-hand side is returned as the value of the whole expression.
(expr1, expr2) is like { expr1; expr2; } but you can use the result of expr2 in a function call or assignment.
It is often seen in for loops to initialise or maintain multiple variables like this:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Apart from this, I've only used it "in anger" in one other case, when wrapping up two operations that should always go together in a macro. We had code that copied various binary values into a byte buffer for sending on a network, and a pointer maintained where we had got up to:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Where the values were shorts or ints we did this:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Later we read that this was not really valid C, because (short *)ptr is no longer an l-value and can't be incremented, although our compiler at the time didn't mind. To fix this, we split the expression in two:
*(short *)ptr = short_value;
ptr += sizeof(short);
However, this approach relied on all developers remembering to put both statements in all the time. We wanted a function where you could pass in the output pointer, the value and and the value's type. This being C, not C++ with templates, we couldn't have a function take an arbitrary type, so we settled on a macro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
By using the comma operator we were able to use this in expressions or as statements as we wished:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
I'm not suggesting any of these examples are good style! Indeed, I seem to remember Steve McConnell's Code Complete advising against even using comma operators in a for loop: for readability and maintainability, the loop should be controlled by only one variable, and the expressions in the for line itself should only contain loop-control code, not other extra bits of initialisation or loop maintenance.
It causes the evaluation of multiple statements, but uses only the last one as a resulting value (rvalue, I think).
So...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
should result in x being set to 8.
As earlier answers have stated it evaluates all statements but uses the last one as the value of the expression. Personally I've only found it useful in loop expressions:
for (tmp=0, i = MAX; i > 0; i--)
The only place I've seen it being useful is when you write a funky loop where you want to do multiple things in one of the expressions (probably the init expression or loop expression. Something like:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Pardon me if there are any syntax errors or if I mixed in anything that's not strict C. I'm not arguing that the , operator is good form, but that's what you could use it for. In the case above I'd probably use a while loop instead so the multiple expressions on init and loop would be more obvious. (And I'd initialize i1 and i2 inline instead of declaring and then initializing.... blah blah blah.)
I'm reviving this simply to address questions from #Rajesh and #JeffMercado which i think are very important since this is one of the top search engine hits.
Take the following snippet of code for example
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
It will print
1 5
The i case is handled as explained by most answers. All expressions are evaluated in left-to-right order but only the last one is assigned to i. The result of the ( expression )is1`.
The j case follows different precedence rules since , has the lowest operator precedence. Because of those rules, the compiler sees assignment-expression, constant, constant .... The expressions are again evaluated in left-to-right order and their side-effects stay visible, therefore, j is 5 as a result of j = 5.
Interstingly, int j = 5,4,3,2,1; is not allowed by the language spec. An initializer expects an assignment-expression so a direct , operator is not allowed.
Hope this helps.

Assigning Values to variables in c [duplicate]

What does the , operator do in C?
The expression:
(expression1, expression2)
First expression1 is evaluated, then expression2 is evaluated, and the value of expression2 is returned for the whole expression.
I've seen used most in while loops:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
It will do the operation, then do a test based on a side-effect. The other way would be to do it like this:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
The comma operator will evaluate the left operand, discard the result and then evaluate the right operand and that will be the result. The idiomatic use as noted in the link is when initializing the variables used in a for loop, and it gives the following example:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Otherwise there are not many great uses of the comma operator, although it is easy to abuse to generate code that is hard to read and maintain.
From the draft C99 standard the grammar is as follows:
expression:
assignment-expression
expression , assignment-expression
and paragraph 2 says:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. 97) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
Footnote 97 says:
A comma operator does not yield an lvalue.
which means you can not assign to the result of the comma operator.
It is important to note that the comma operator has the lowest precedence and therefore there are cases where using () can make a big difference, for example:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
will have the following output:
1 4
The comma operator combines the two expressions either side of it into one, evaluating them both in left-to-right order. The value of the right-hand side is returned as the value of the whole expression.
(expr1, expr2) is like { expr1; expr2; } but you can use the result of expr2 in a function call or assignment.
It is often seen in for loops to initialise or maintain multiple variables like this:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Apart from this, I've only used it "in anger" in one other case, when wrapping up two operations that should always go together in a macro. We had code that copied various binary values into a byte buffer for sending on a network, and a pointer maintained where we had got up to:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Where the values were shorts or ints we did this:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Later we read that this was not really valid C, because (short *)ptr is no longer an l-value and can't be incremented, although our compiler at the time didn't mind. To fix this, we split the expression in two:
*(short *)ptr = short_value;
ptr += sizeof(short);
However, this approach relied on all developers remembering to put both statements in all the time. We wanted a function where you could pass in the output pointer, the value and and the value's type. This being C, not C++ with templates, we couldn't have a function take an arbitrary type, so we settled on a macro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
By using the comma operator we were able to use this in expressions or as statements as we wished:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
I'm not suggesting any of these examples are good style! Indeed, I seem to remember Steve McConnell's Code Complete advising against even using comma operators in a for loop: for readability and maintainability, the loop should be controlled by only one variable, and the expressions in the for line itself should only contain loop-control code, not other extra bits of initialisation or loop maintenance.
It causes the evaluation of multiple statements, but uses only the last one as a resulting value (rvalue, I think).
So...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
should result in x being set to 8.
As earlier answers have stated it evaluates all statements but uses the last one as the value of the expression. Personally I've only found it useful in loop expressions:
for (tmp=0, i = MAX; i > 0; i--)
The only place I've seen it being useful is when you write a funky loop where you want to do multiple things in one of the expressions (probably the init expression or loop expression. Something like:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Pardon me if there are any syntax errors or if I mixed in anything that's not strict C. I'm not arguing that the , operator is good form, but that's what you could use it for. In the case above I'd probably use a while loop instead so the multiple expressions on init and loop would be more obvious. (And I'd initialize i1 and i2 inline instead of declaring and then initializing.... blah blah blah.)
I'm reviving this simply to address questions from #Rajesh and #JeffMercado which i think are very important since this is one of the top search engine hits.
Take the following snippet of code for example
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
It will print
1 5
The i case is handled as explained by most answers. All expressions are evaluated in left-to-right order but only the last one is assigned to i. The result of the ( expression )is1`.
The j case follows different precedence rules since , has the lowest operator precedence. Because of those rules, the compiler sees assignment-expression, constant, constant .... The expressions are again evaluated in left-to-right order and their side-effects stay visible, therefore, j is 5 as a result of j = 5.
Interstingly, int j = 5,4,3,2,1; is not allowed by the language spec. An initializer expects an assignment-expression so a direct , operator is not allowed.
Hope this helps.

Same as i++ but for more complex operation

I'm not facing any problem. This question is just about C language
Let's say I have a function like:
int func()
{
static int i = 1;
return(i++);
}
Now, instead of doing i++ (i+=1) I'd like to do i *= 42; but still return the value before the multiplication.
I'm wondering if there is a way to do it the same way that i++ works (in one expression, take value of i and then do i *= 42).
Postfix ++ and -- are the only C operators that modify an object and yield that object's previous value. If you want to do that for anything other than incrementing or decrementing by 1, you'll have to store the previous value in a temporary.
If you wanted to design your own language, you could implement a "reverse comma" operator that yields its left operand rather than its right operand. (The existing comma operator evaluates its left operand, then evaluates its right operand, then yields the value of the right operand.)
For example, if the "reverse comma" were spelled ,,, you could do:
return i ,, i *= 42; /* THIS IS NOT C */
int func()
{
static int i = 1;
int tmp = i;
i *= 42;
return tmp;
}
An assignment is an expression is C. So you could code
int func() {
static int i = 1;
return(i *= 42);
}
Of course if you wanted to return i before multiplying it you need another variable.

Resources