11

Prog 1:

#include<stdio.h> int main() {     int i=0;     while(i<=8,i++);     printf("%d",i);     return 0;  }

Prog 2:

#include<stdio.h> int main(){  int i=0;  while(i++,i<=8);  printf("%d",i);  return 0;}

The output of Prog 1 is 1 and that of Prog 2 is 9.

Can someone explain whats going here. How the two codes are different?

Zoe - Save the data dump's user avatar
Zoe - Save the data dump
28.4k22 gold badges130 silver badges163 bronze badges
askedJan 12, 2017 at 11:05
Adnan's user avatar
1
  • 2
    I would argue that this question is not a duplicate. Sure, with proper understanding of, separately, the while loop syntax and comma operator syntax and functioning one would be able to understand this problem without external help. But I don't think it's right to assume a question is not proper just because knowledge would have prevented the question. Questions arising from confusion can be helpful too, because many people can be confused in exactly the same way, benefiting from tailored explanation of both concepts intricacies and their relationship.CommentedJul 30, 2020 at 22:39

3 Answers3

12

The comma operator evaluates both of its arguments in turn, throwing away the result, except for the last. The last evaluated expression determines the result of the entire expression.

i<=8,i++ - here the value of the expression is the value ofi++, which is the value ofi before being incremented. It's 0 so the loop immediately terminates.

i++,i<=8 - here the value of the expression is the value ofi<=8 which is 0 only wheni is incremented to 9.

On a personal note: I think the second form, while somewhat comparable to a for loop, is less clear to the reader of the code than an actual for loop.

answeredJan 12, 2017 at 11:08
StoryTeller - Unslander Monica's user avatar
Sign up to request clarification or add additional context in comments.

Comments

2
1 while ( condition )2    statement;3 more_code();

In the above code snippet, thestatement can be executed repeatedly as long ascondition istrue. On each iteration of the while loop,condition is evaluated to eithertrue orfalse. If it'sfalse, the while loop ends and execution continues beyond it's scope (in this case, line 4 withmore_code().

We are usually accustomed to enclosing parts of code that we want to be executed in loop with curly brackets{ and}, but that is not mandatory. If we do not do so, the looping code will consist of single statement, the one immediately following thewhile part.

It could actually be argued that the more common situation, where we combinewhile with curly brackets enclosedblock of code could be interpreted as providing this block of codein place of a single statement, with braces providing information that the block should be treated (by compiler analysing it's relation with preceding and following code)as if it was a single statement.

However, as it is perfectly valid to provide a single statement, not a usual block of code, it's worth to understand that there is a valid statement that is empty. We get an empty statement by typing a semicolon without preceding it with a code causing anything. So following is perfectly valid:

1 code;2 ; // empty statement3 ; // another empty statement

or in fact this:

1 code;; // a "code" statement followed by empty statement in the same line

Thewhile( condition ) part is not terminated with a semicolon, so if it's supposed to control some actual code (apart fromcondition), it should not be followed by a semicolon. If it is immediately followed by a semicolon, that semicolon will constitute (and be so interpreted by compiler) an empty statement, so the looping code will be empty. If that's unintended, then the code we wanted to be looped, whether a block of code or a statement, will not be looped, but rather executed once, after (and if) loop ends.

1 int a = 0;2 while ( a < 3 ) ; // Next line is not part of loop - only the empty statement this semicolon creates is. This loop is infinite, or in other words it will never end.3    a++; // This won't be executed even once.4 printf("This never happens.");

(It's worth realizing that lines are only important for us, humans, in C. Lines and indentation can be misleading if they represent the intentions of programmer, when he failed to write the code functioning as he wanted it to.)

Therefore what happens in both snippets from the question, is we getcondition evaluated continuously until it yieldsfalse. To understand what's going on we need to examine the way comma operator works.

(Note, while comma as a character can be used with a completely different meaning in various places in C - I can think of function declarations, definitions and calls - in this case comma character is part of condition, therefore it acts as anoperator - something akin to+ or% operators.)

expression1 , expression2

Comma operator causesexpression1 to be evaluated first, thenexpression2, and returns the value ofexpression2.

Upon every evaluation of condition, we will thus evaluate both expressions, (in this case both being operands,i++ andi<=8), then consider value of the right one as result of comma operand itself, and thus as value of our condition. So the loop will keep repeating as long as the right operand resolves astrue.

While usually we use condition to control the execution of loop, often, as in this case,condition may have "side" effects (intentional or unintended). In our case variablei is affected by every evaluation ofcondition: it is increased by one.

Our example differs only in order of operands ofcondition, therefore pay attention to the right operand which really controls the execution of the loop.

Let's examine the second example first. In this case we have conditioni++, i<=8. This means upon every evaluation we first increasei, then check if it's less than or equal to 8. So on first evaluation of condition we will increasei from 0 to 1 and conclude that 1<=8, so the loop continues. The loop so constructed will break wheni becomes 9, ie. on the 9th iteration.

Now as for the first example, the condition isi<=8, ++i. Since comparison has no side effects, that is we could perform any number of comparisons in any order and if that's the only thing we did, that is if we did not perform any other action in a way or order dependent of results of the comparisons, those comparisons would do absolutely nothing. As is in our case, we evaluatei<=8 which evaluates totrue orfalse, but we make no use of this result, just proceed to evaluating the right operand. So left operand absolutely doesn't matter. Right operand, on the other hand, has both a side effect and it's value becomes value of entire condition. Before each loop iteration we check ifi++ evaluates totrue orfalse.

i++ is a unary operator of post-incrementation. It returns value ofithen increases it by one (the difference between i++ and ++i is subtle but crucial in cases like this one). So what happens is we first check whetheri istrue orfalse, theni is increased by one.

In C there is noboolean type. Integers are considered to betrue if they have a non-zero value.

So upon first evaluation ofi++ we get 0, that isfalse. This means the loop is broken without even a single iteration. However it does not break evaluation ofi++, which causesi to increase by one before we're done with the loop and execution proceeds beyond it. So once we're done with the while loop,i is already 1.

If we want to be very precise in our understanding, the part where we take the result of evaluating entire condition happens, chronologically,after we are finished executing any code involved in this evaluation. So we first memorize thati was 0 at the point we got towardi++ part, then we increasei by one, and then we are finished executingcondition, so we provide value of 0 to the code that decides if we should do another (in this case first) iteration or jump beyond looping part and move on. This is exact reason why everything within condition will actually happen even though the fact that loop will end was already determined: it was determined, but it was not checked and acted upon untilcondition finishes executing.

answeredJan 12, 2017 at 11:41
szpanczyk's user avatar

1 Comment

@bhass1 while your edit is appreciated, adding curly brackets takes away value in this particular situation. Curly brackets are not part of snippet in question, do you see what I mean? Curly brackets, as you probably know, are not mandatory and their absence may be confusing to some new programmers and needs to be part of proper answer in this case.
1

The expression separator operator, forces evaluation from left to right, and is also asequencing point.

Prog 1: consideri <= 8, i++.i <= 8 is evaluated and discarded theni++ is evaluated. The entire expression has the unincremented value ofi. Sincei is initially0, thewhile loop terminates on the first iteration. The output will be that singly incremented value ofi, i.e. 1.

Prog 2:i++ is evaluated and the result discarded, theni <= 8 is evaluated with thenew value ofi since, is asequencing point. So thewhile loop runs untili <= 8 is no longertrue with the incremented value ofi. The output will be 9.

answeredJan 12, 2017 at 11:10
Bathsheba's user avatar

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.