This question already has an answer here:
what is the difference between while(i>0) and while(i)
(1 answer)
Closed 6 months ago.
I am trying to run a program in C, where the following statement is used in the code.
What does the following statement mean in the for loop condition of the given code?
I understand i is being initialised with value 3; and i gets updated in i = i-1 ; but what does the condition part mean? why only i; should it not be i>0? Why both statements give the same output , i.e *** .
Code statements:
int main()
{
for(int i=3;i;i=i-1)
{
printf("*");
}
return 0;
}
Simply, i will be true when != 0. Since your program must keep going until i is zero, It will keep checking. Here's a list of what the condition returns:
i value
output returned by i
3
true
2
true
1
true
0
false (break)
C 2018 6.8.5.3 discusses the for statement, which has the form for (clause-1; expression-2; expression-3) statement, and paragraph 1 says:
… The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body…
6.8.5 4 says:
An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
Therefore, with i for the controlling expression, the loop body is executed repeatedly until i compares equal to zero.
Related
#include <stdio.h>
int main(void) {
char i=250;
for(i<0;i++;i=0,printf("%d", i));
return 0;
}
In this program, the output is 0. From what i understand is, a for loop should have the first parameter as initialisation, then condition, then increment. But in this question the initialisation is happening at the last and still the code is giving valid result. Can someone explain how?
The clauses or expressions in a for statement are always interpreted based on where they are (first, second, or third) in the for statement. In this code:
char i=250;
for(i<0;i++;i=0,printf("%d", i));
return 0;
i is set to either 250 (if char is unsigned) or −6 (if char is signed, eight-bit, and typical two’s complement wrapping is used for the conversion from 250 to char). (The C standard permits other possibilities, but they are unusual and are not discussed further in this answer.)
To start the loop, the initial clause i<0 is evaluated. Its result is inconsequential because it is ignored.
To decide whether the loop ends, the test clause i++ is evaluated. This produces either 250 or −6, per the above, and, separately, increments i to either 251 or −5. In either case, the result of the expression is non-zero, so the loop continues.
The body of the loop, ; is evaluated. Since this is an empty statement, it has no effect.
The post-iteration clause, i=0,printf("%d", i) is evaluated. This sets i to 0 and prints i, resulting in output of “0”.
The test clause i++ is evaluated again. Since i is zero, this produces 0, and, separately, increments i to 1. Since the result of the expression is zero, the loop terminates.
return 0; is executed, cause the program to end with a success status.
Short answer to your question "Can we interchange the for loop parameters in C?" is: No .
This code, if not meant to confuse the reader, must be a badly written one.
Walk-through
i is initialized with a value 250
i<0 as the initialization step is ignored
i++ is executed, since the old i is not 0, the loop continues
nothing in the loop body
set i=0 and print its value 0 out
come back to the i++, noting that the previous i value is zero, so loop stops
Actually for loop works in the following way:
for (step 0; step 1; step 3) {
step 2;
}
Here, step 0 is executed only once. Then step 1 -> step 2 -> step 3 -> step 1 and the loop goes on.
a for loop should have the first parameter as initialisation, then condition, then increment.
this is more like a convention. And explaining the for loop in this way makes perfect sense (especially because in step 1, the program executes the statement and continues to step 2 only when it returns true). And so we utilize for loop in this way.
"Can we interchange the for loop parameters in C?"
We can interchange the expressions itself (for whatever reason, for example as experiment because it usually makes no sense to do so), but we can't change the syntax (how an expression is evaluated at a certain place).
A for loop has a fixed syntax following conventionally the form:
for (initializations; condition; in-/decrements)
You can use expressions where you want to but it has quite different effects.
If you place for example the initialization expressions at the second place they are used as condition.
Same goes if you would take the in-/decrements and place them at the second place. Then they would be evaluated as condition, too.
Equivalently, if you would place the expression used as condition at the first or third place, this expression will not be used as the condition anymore.
That's what the C standard says to this topic:
6.8.5.3 The for statement
1 The statement
for (clause-1; expression-2; expression-3) statement
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. Ifclause-1is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.161)
2 Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a non zero constant.
Source: ISO/IEC 9899:2018 (C18), §6.8.5.3
A for loop for(init; cond; inc) { body } Is basically executed like this:
init;
while(cond) {
body;
inc;
}
For some cases it is possible to switch things, but in the general case it is not.
I tried this code and got the output below. But I don't understood how it came.
What is the logic involved in this snippet of code? Can you explain?
Also when ++i is replaced by i++ it gives different output??
int main()
{
char i= 0;
for(i<=5 && i>=-1;++i;i>0)
printf("%d\n",i);
printf("\n");
return 0;
}
Output:
1 2 3 .... 126 127 -128 -127 .... 2 1.
it is because of the for loop you have written
for(i<=5 && i>=-1;++i;i>0)
the first option in for loop is executed once. it doesn't check whether the condition is true or not, nor doesn't control the loop execution. even though the expression evaluated to 0, the loop starts executing.
the second part is executed every time the loop begins, and it is the loop breaking condition. that is, if this expression results 0, it breaks.
the third section executes every time, again, doesn't affect the loop execution.
NOw let's analyze your code.
i is initialized to 0 before entering the loop.
initializer in for loop does a condition check, i<=5 && i>=-1 but doesn't change the value of i.
the condition section does an increment to the variable i, which happens every time it enters the loop. so the value goes from 0,1,2,..127,-128,-127...-1 ( since it is signed char which ranges from -128 to 127) and then reaches 0, which means false. when it evaluates to 0, the for loop breaks. thus the output you got.
the 3rd section is again a condition, which doesn't update the value.
you might want to check the syntax of loop, and what is the output you are expecting.
This is what the C standard says about for loops:
The statement for
( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling
expression that is evaluated before each execution of the loop body.
The expression expression-3 is evaluated as a void expression after
each execution of the loop body. If clause-1 is a declaration, the
scope of any identifiers it declares is the remainder of the
declaration and the entire loop, including the other two expressions;
it is reached in the order of execution before the first evaluation of
the controlling expression. If clause-1 is an expression, it is
evaluated as a void expression before the first evaluation of the
controlling expression.
The for loop starts printing with i equal to 1. i wraps around after reaching the max value possible for the char datatype. The loop terminates when expression-2 i.e. ++i in this case is 0. ++i evaluates to 0 when i is -1.
Also note that overflowing a signed number results in undefined behaviour. The char data type may be signed or unsigned based on your system.
This question already has answers here:
Two semicolons inside a for-loop parentheses
(4 answers)
Closed 4 years ago.
How does a for loop work internally in terms of the machine language when the expressions are not written. For example
int i=0 , j=1;
for(;;)
A for loop with a missing middle expression is an infinite loop.
From section 6.8.5.3 of the C standard:
1 The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling
expression that is evaluated before each execution of the loop body.
The expression expression-3 is evaluated as a void expression after
each execution of the loop body. If clause-1 is a declaration, the
scope of any identifiers it declares is the remainder of the
declaration and the entire loop, including the other two expressions;
it is reached in the order of execution before the first evaluation of
the controlling expression. If clause-1 is an expression, it is
evaluated as a void expression before the first evaluation of the
controlling expression.
2 Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
Because a missing "expression-2" is replaced with a non-zero constant, and because a non-zero value evaluates to true, this gives you an infinite loop.
All the parts of the for-loop are optional:
initialization: you can do the initialization outside of the loop.
condition: will be true if empty
last part: you can also do nothing.
for(;;) is an infinite loop (if there are no breaks inside the loop).
The expressions which are not present do nothing.
If the initialisation is absent, nothing is initialised.
If the test is absent, nothing is tested (and the body loops forever unless it contains abreak, return, etc.)
If the increment is absent, nothing is incremented.
The for loop contains three clauses. They can be virtually any expression, but the standard way of using it is for(<init>; <loop condition>; <loop variable increment>). All of these are optional: if you omit the loop condition, it will be replaced by a constant that evaluates to true. You could for instance replace
for(int i=0; i<10; i++) {
...
}
with
for(int i=0; i<10; ) {
...
i++;
}
for(;;) is an infinite loop. Any for loop that has second statement omitted is an infinite loop.
There are basically three ways to get out of an infinite loop, break, return and goto.
In most cases you should use break or return, but goto also has its usage.
If you want to just break out of the loop and continue after it, use break.
If you want to quit the function that contains the loop, use return. However, this can be bad practice since it will likely violate the "single exit" practice.
If you want to break out of a nested loop, goto may be appropriate.
And yes, you could exit a loop by calling exit() or simply make the program crash too, but I think you get the point.
Question from comments
for(i<2; i++; )
This does not make much sense. The first expression i<2 will not affect anything and is likely to be optimized away by the compiler. The second expression i++ will evaluate to false if i is 0:
if i has an initial value of 0, the loop body is not evaluated at all.
if i is initially a negative number. The loop iterates until i reaches the value 0, the last iteration occurs with i == 0 and the next test will end the loop.
if i has an unsigned type and is greater than 0. The loop iterates until i reaches the maximum value for its type and wraps to 0, the last iteration occurs with i == 0 and the next test stops the loop. If i is not unsigned, arithmetic overflow will cause undefined behavior, which is bad: the loop may stop or continue indefinitely, depending on the compiler choices, or anything else may occur.
This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 6 years ago.
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?
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 of i++, which is the value of i before being incremented. It's 0 so the loop immediately terminates.
i++,i<=8 - here the value of the expression is the value of i<=8 which is 0 only when i 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.
1 while ( condition )
2 statement;
3 more_code();
In the above code snippet, the statement can be executed repeatedly as long as condition is true. On each iteration of the while loop, condition is evaluated to either true or false. If it's false, the while loop ends and execution continues beyond it's scope (in this case, line 4 with more_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 the while part.
It could actually be argued that the more common situation, where we combine while with curly brackets enclosed block of code could be interpreted as providing this block of code in 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 statement
3 ; // another empty statement
or in fact this:
1 code;; // a "code" statement followed by empty statement in the same line
The while( condition ) part is not terminated with a semicolon, so if it's supposed to control some actual code (apart from condition), 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 get condition evaluated continuously until it yields false. 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 an operator - something akin to + or % operators.)
expression1 , expression2
Comma operator causes expression1 to be evaluated first, then expression2, and returns the value of expression2.
Upon every evaluation of condition, we will thus evaluate both expressions, (in this case both being operands, i++ and i<=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 as true.
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 variable i is affected by every evaluation of condition: it is increased by one.
Our example differs only in order of operands of condition, 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 condition i++, i<=8. This means upon every evaluation we first increase i, then check if it's less than or equal to 8. So on first evaluation of condition we will increase i from 0 to 1 and conclude that 1<=8, so the loop continues. The loop so constructed will break when i becomes 9, ie. on the 9th iteration.
Now as for the first example, the condition is i<=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 evaluate i<=8 which evaluates to true or false, 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 if i++ evaluates to true or false.
i++ is a unary operator of post-incrementation. It returns value of i then 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 whether i is true or false, then i is increased by one.
In C there is no boolean type. Integers are considered to be true if they have a non-zero value.
So upon first evaluation of i++ we get 0, that is false. This means the loop is broken without even a single iteration. However it does not break evaluation of i++, which causes i 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 that i was 0 at the point we got toward i++ part, then we increase i by one, and then we are finished executing condition, 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 until condition finishes executing.
The expression separator operator , forces evaluation from left to right, and is also a sequencing point.
Prog 1: consider i <= 8, i++. i <= 8 is evaluated and discarded then i++ is evaluated. The entire expression has the unincremented value of i. Since i is initially 0, the while loop terminates on the first iteration. The output will be that singly incremented value of i, i.e. 1.
Prog 2: i++ is evaluated and the result discarded, then i <= 8 is evaluated with the new value of i since , is a sequencing point. So the while loop runs until i <= 8 is no longer true with the incremented value of i. The output will be 9.
can anyone explain the working of the for loop in the following code:
#include<stdio.h>
#include<conio.h>
int main()
{
char i=0;
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
getch();
}
Let's break the for statement down, we have three phases, the initialiser, the test, and the modifier:
for(<Initialiser>; <Test>; <Modifier>)
<content>;
In your case:
for(i<=5&&i>=-1;++i;i>0)
// initialiser: i<=5&&i>=-1;
// test: ++i;
// modifier: i>0
The initialiser is done first. Here no assignment is done. Two boolean expressions (denoted by the >= and <= operators are compared in a logical &&. The whole initialiser returns a boolean value but it doesn't do anything. It could be left as a blank ; and there would be no change.
The test uses the pre-increment operator and so returns the result of i+1. If this result is ever 0 it evaluates as false and the loop will terminate. For any non-zero value it evaluates to true and continues. This is often used when i is initialised to a value less than zero and so the test will increment i until i+1 results in a zero, at which point the loop terminates.
Finally we have the modifier, which in this case simply uses the > operator to evaluate to a boolean value. No assignment is done here either.
The fact is that you've gotten the test and the modifier confused and put them in the wrong positions but before we sort that out let's see how it would work…
We begin with:
char i = 0;
…and for all intents and purposes this does the same thing as our for loops initialiser would do in normal circumstances. The next thing to be evaluated is the for loop's initialiser:
i<=5 && i>=-1;
Because i is 0 it is less-than-or-equal-to 5 and it is greater-than-or-equal-to -1. This expression evaluates to 1 but nothing is done with that value. All we've done is waste a bit of time with an evaluation.
Next up is the modifier to test whether or not the for loop's inner block should be executed:
++i;
This evaluates to 1 and also assigns that value to i. Now, as it's evaluated to a non-zero number, the loop executes:
printf("%d\n",i);
And the digit 1 is printed to the screen... Now it's the modifier that gets executed:
i>0
Well, i is 1 so that is greater-than 0. This evaluates to 1 (or true). Either way, this is ignored. The purpose of the modifier isn't to test or check anything. It's there so that you can change the state of the program each time the for loop iterates. Either way, the loop repeats and it will do this for a very long time. Why? Because ++i is going to evaluate to a non-zero number for a while. Whether or not it will ever terminate depends on how your system deals with integer overflows.
This is what you meant to do:
#include<stdio.h>
#include<conio.h>
int main()
{
for(char i=0; i<=5&&i>=-1; ++i)
printf("%d\n",i);
}
Do you see the difference? Our initialiser now starts the loop with the state of i as zero. We then test if it's within the bounds of -1 to 5 and each time we iterate we increment i by 1. This loop will output:
0
1
2
3
4
5
This snippet:
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
Does the same as this:
i<=5 && i>=-1; //statement with no effect
while(++i)
{
printf("%d\n",i);
i>0; //statement with no effect
}
So, it's going to print i until ++i evaluates to 0. This will happen after i overflows and becomes negative, then incrementing towards 0. That will take 255 iterations to happen, since chars can store up to 256 different values.
for ( variable initialization; condition; variable update ) {
}
the variable initialization phase is done only once when the for loop starts.
the condition is checked everytime before running code inside the loop. if the condition is false then the loop is exited.
the variable update is done after the first iteration, from the second iteration it is done before the condition check.