33

I came across this piece of code. I generally use '&&' or '||' to separate multiple conditions in a for loop, but this code uses commas to do that.

Surprisingly, if I change the order of the conditions the output varies.

#include<stdio.h>

int main() {
    int i, j=2;

    for(i=0; j>=0,i<=5; i++)
    {
         printf("%d ", i+j);
         j--;
    }
    return 0;
}

Output = 2 2 2 2 2 2

#include<stdio.h>

int main(){
    int i, j=2;

    for(i=0; i<=5,j>=0; i++)
    {
         printf("%d ", i+j);
         j--;
    }
    return 0;
}

Output = 2 2 2

Can somebody explain the reason? It seems to be checking only the last comma-separated condition.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prateek
  • 685
  • 1
  • 7
  • 7
  • 3
    Bad code. You're right; multiple conditions should be joined with && or ||. – Caleb May 31 '13 at 13:59
  • 10
    Five answers, everybody taking the question overly literally and explaining what a comma does, and not a single answer suggesting that this is horribly, horribly broken. – Edward Thomson May 31 '13 at 14:00
  • According to the search engines, this is the canonical question. However, this kind of question ***must*** have been asked in 2008 or 2009. What is it? – Peter Mortensen Sep 01 '22 at 22:09
  • Here is [one from 2011](https://stackoverflow.com/questions/7823732/c-do-while-loop-with-two-different-conditions), but it is not really canonical. – Peter Mortensen Sep 01 '22 at 22:27
  • It is a strange place for the comma operator. Perhaps from some programming quiz? I expected there to be a canonical question about its normal idiomatic use, but I couldn't find it (why wouldn't *"What is the purpose of the comma operator here"* has been asked?). Wikipedia [has it](https://en.wikipedia.org/wiki/Comma_operator#For_loops): *"The most common use is to* ***allow multiple assignment statements without using a block statement***, *primarily in the initialization and the increment expressions of a* ***for loop.*** *This is the only idiomatic use in elementary C programming."* – Peter Mortensen Sep 11 '22 at 00:38

7 Answers7

65

The comma operator evaluates all its operands and yields the value of the last one. So basically whichever condition you write first, it will be disregarded, and the second one will be significant only.

for (i = 0; j >= 0, i <= 5; i++)

is thus equivalent with

for (i = 0; i <= 5; i++)

which may or may not be what the author of the code intended, depending on his intents - I hope this is not production code, because if the programmer having written this wanted to express an AND relation between the conditions, then this is incorrect and the && operator should have been used instead.

  • 1
    The important point here is tat the code in question is incorrect. – Caleb May 31 '13 at 14:02
  • 1
    @Caleb In what sense? I think I get what you are trying to suggest, I'm just not sure it can or should be included in the answer as-is. –  May 31 '13 at 14:03
  • This *cannot* be what the author intended, as it is meaningless. I would not trust any code by this author. – Lee Daniel Crocker May 31 '13 at 14:06
  • 4
    The first condition, `j>=0`, is evaluated but the result is never used. The loop will continue as long as I doesn't exceed 5, even if j is less than 0. It *looks* like the loop will stop at j = -1, but it won't. Hard to call that anything other than broken. – Caleb May 31 '13 at 14:07
  • Yes its not production code. I was just revising my C basics and came across a website which had some multiple choice questions where I came across this. Thanks for the response. – Prateek May 31 '13 at 21:17
  • @Caleb In fact `j>=0` may never even be evaluated, because the compiler is likely to notice that its value is never used, and it has no side effects, so it can be tossed as dead code... – twalberg Nov 20 '13 at 21:55
11

Of course it is right what you say at the beginning, and C logical operator && and || are what you usually use to "connect" conditions (expressions that can be evaluated as true or false); the comma operator is not a logical operator and its use in that example makes no sense, as explained by other users. You can use it e.g. to "concatenate" statements in the for itself: you can initialize and update j altogether with i; or use the comma operator in other ways

#include <stdio.h>

int main(void)  // as std wants
{
  int i, j;

  // init both i and j; condition, we suppose && is the "original"
  // intention; update i and j
  for(i=0, j=2; j>=0 && i<=5; i++, j--)
  {
       printf("%d ", i+j);
  }
  return 0;        
}
Community
  • 1
  • 1
ShinTakezou
  • 9,432
  • 1
  • 29
  • 39
5

The comma expression takes on the value of the last (eg. right-most) expression.

So in your first loop, the only controlling expression is i<=5; and j>=0 is ignored.

In the second loop, j>=0 controls the loop, and i<=5 is ignored.


As for a reason... there is no reason. This code is just wrong. The first part of the comma-expressions does nothing except confuse programmers. If a serious programmer wrote this, they should be ashamed of themselves and have their keyboard revoked.

abelenky
  • 63,815
  • 23
  • 109
  • 159
3

Do not use this code; whoever wrote it clearly has a fundamental misunderstanding of the language and is not trustworthy. The expression:

j >= 0, i <= 5

evaluates "j >= 0", then throws it away and does nothing with it. Then it evaluates "i <= 5" and uses that, and only that, as the condition for ending the loop. The comma operator can be used meaningfully in a loop condition when the left operand has side effects; you'll often see things like:

for (i = 0, j = 0; i < 10; ++i, ++j) . . .

in which the comma is used to sneak in extra initialization and increment statements. But the code shown is not doing that, or anything else meaningful.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
2

There is an operator in C called the comma operator. It executes each expression in order and returns the value of the last statement. It's also a sequence point, meaning each expression is guaranteed to execute in completely and in order before the next expression in the series executes, similar to && or ||.

Robert S. Barnes
  • 39,711
  • 30
  • 131
  • 179
2

Wikipedia tells what comma operator does:

"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)."

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tafa
  • 7,146
  • 3
  • 36
  • 40
  • 1
    -1 Quoting from Wikipedia doesn't answer the question, which is not what does the comma do but rather why is it being used here. – Caleb May 31 '13 at 14:09
  • 1
    @Caleb, honestly I do not believe the question asks why. Because it says: "Surprisingly, if i change the order of the conditions the output varies". Hence quoting answers it. – tafa May 31 '13 at 14:15
0

Completing Mr. Crocker's answer, be careful about ++ or -- operators or I don't know maybe other operators. They can affect the loop. for example I saw a code similar to this one in a course:

for(int i=0; i++*i<-1, i<3; printf(" %d", i));

The result would be $ 1 2$. So the first statement has affected the loop while the outcome of the following is lots of zeros.

for(int i=0; i<3; printf(" %d", i));
Nikos M.
  • 13,685
  • 4
  • 47
  • 61
MSN
  • 1