I know this is a stupid question to ask but i am just asking this out of my curiosity.
I just read this code somewhere:
#include<stdio.h>
int main() {
for ( ; 0 ; )
printf("This code will be executed one time.");
return 0;
}
Output:
This code will be executed one time.
This loop is executing once in Turbo C compiler while not working in gcc, but how can this be possible that this loop execute even for once?
Can you please guide me for the unusual behavior of this code in the Turbo C compiler, if there is any?
It's a bug in the compiler. The C99 standard describes for loops like this:
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. [...]
Given that expression-2 evaluates to false, the code should print no output.
TurboC does not follow the C99 standard. This could explain the unusual behaviour.REst assured, gcc will give you the correct output.
Related
int main() {
for(3;2;1)
printf("hello\n")
}
I thought this loop wouldn't even be executed. AFAIK we have to define a variable; put a condition; increase/decrease. However in this code none of the things I counted exists. So I think this program should crash. But it goes on forever.
Because the exit condition (2) is always true.
This works because the format of a for statement is
for (clause-1;expression-2;expression-3)
Where clause-1 can be a declaration (e.g. int i = 0) or an expression.
In your case you have three expressions, so the statement is still syntactically valid.
The loop exits when expression-2 evaluates to false (0) which, in your case, it never does since it's a non-zero constant (2).
The stopping conditional expression 2 is never zero.
So the loop runs forever.
AFAIK we have to define a variable; put a condition; increase/decrease. However in this code none of the things I counted exists. So I think this program should crash. But it goes on forever.
While learning about for loops you were likely exposed to a very specific use of a loop, and therefore extrapolated about what may or may not appear there syntactically. But you didn't get the whole picture. There is a standard for that C language, and it is that standard which defines how a loop may be written and how it will behave. For a loop, we may look at §6.8.5 (Iteration statement) to determine the correct behavior:
iteration-statement:
while ( expression ) statement
do statement while ( expression ) ;
for ( expressionopt ; expressionopt ; expressionopt ) statement
for ( declaration expressionopt ; expressionopt ) statement
That's the grammar for all loops. See how the for loop allows an arbitrary expression in all 3 places? Since even 1, 2, and 3 are expressions in C, they can go there. And the standard even tells us what the behavior should be:
An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
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.
So 2 must be evaluated, and compared equal to 0. Which will never occur, hence the behavior you observed.
C is not Bourne shell like in for i in 3 2 1 ; do echo hello ; done
The proper loop is like this:
#include <stdio.h>
int main() {
for(int i = 1; i <=3 ; i++)
printf("hello\n");
}
Here, the conditional expression i <= 3 isn't always true like 2 is. True is any non-zero value.
we know 0 is false and 1 is true. In this case, in conditional statement for( ;2;) is always true like while(2). so it will run infinitely.
.
A for loop doesn’t require the use of any variables. It simply specifies the use of three expressions, each of which may be optional:
for ( expression-1opt ; expression-2opt ; expression-3opt ) statement
First, expression-1 is evaluated (if it is present). This expression typically initializes the condition we’ll test for in expression-2, but it doesn’t have to.
Next, expression-2 is evaluated. If the result of the expression is non-zero, then the loop body will be executed. If expression-2 is not present, then it’s implicitly replaced with a 1.
After the loop body has been executed, expression-3 is evaluated. This expression typically updates the condition we test for in expression-2, but again, it doesn’t have to.
Repeat the last two steps until expression-2 evaluates to zero.
In the case of for ( 1; 2; 3 ) ..., 2 evaluates to non-zero, so the loop body executes. Since that value never changes, the loop runs “forever”. You get the same result with for (;;).
void main() {
int i, j=6;
for(; i=j ; j-=2 )
printf("%d",j);
}
By following regular pattern, there should be a condition after first semicolon, but here it is initialization,so this should have given an error.
How is this even a valid format?
But the output is 642
First, let me correct the terminology, the i=j is an assignment, not an initialization.
That said, let's analyze the for loop syntax first.
for ( clause-1 ; expression-2 ; expression-3 ) statement
So, the expression-2 should be an "expression".
Now, coming to the syntax for statement having assignment operator
assignment-expression: conditional-expression unary-expression
assignment-operator assignment-expression
So, as the spec C11 mentions in chapter §6.5.16, the assignment operation is also an expression which fits perfectly for the expression-2 part in for loop syntax.
Regarding the result,
An
assignment expression has the value of the left operand after the assignment,
so, i=j will basically assign the value of j to i and then, the value of i will be used for condition checking, (i.e., non-zero or zero as TRUE or FALSE).
TL;DR Syntactically, there's no issue with the code, so no error is generated by your compiler.
Also, for a hosted environment, void main() should be int main(void) to be conforming to the standard.
i=j is also an expression, the value of which is the value of i after the assignment. So it can serve as a condition.
You'd normally see this type of cleverness used like this:
if ((ptr = some_complex_function()) != NULL)
{
/* Use ptr */
}
Where some programmers like to fold the assignment and check into one line of code. How good or bad this is for readability is a matter of opinion.
Your code does not contain a syntax error, hence the compiler accepts it and generates code to produce 642.
The condition i=j is interpreted as (i = j) != 0.
To prevent this and many similar error patterns, enable more compiler warnings and make them fatal with:
gcc -Wall -W -Werror
If you use clang, use clang -Weverything -Werror
This is a very good question.
To really understand this, you better know how C codes are executed in computer:
First, the compiler will compile the C code into assembly code, then assembly codes will be translated into machine code, which can run in main memory directly.
As for your code:
void main() {
int i, j=6;
for(; i=j ; j-=2 )
printf("%d",j);
}
To figure out why the result is 642, We want to see its assembly code.
Using VS debugging mode, we can see:
Especially look at this:
010217D0 mov eax,dword ptr [j]
010217D3 mov dword ptr [i],eax
010217D6 cmp dword ptr [i],0
010217DA je main+4Fh (010217EFh)
The four lines of assembly code correponding to the C code "i=j", it means, first move the value of j to register eax, then move the value of register eax to i(since computer can not directly move the value of j to i, it just use register eax as a bridge), then compare the value of i with 0, if they are equal, jump to 010217EFh, the loop ends; if not, the loop continues.
So actually it's first an assignment, then a comparision to decide whether the loop is over; as 6 declines to 0 ,the loop finally stops, I hope this can help you understand why the result is 642 :D
I encountered a strange FOR LOOP question in the book. Here is the code for the loop -
#include<stdio.h>
int main()
{
int i=1,j=1;
for(;;)
{
if(i>5)
break;
else
j+=i;
printf("%d\n",j);
i+=j;
}
return 0;
}
The program prints 2 & 5 as the output. Now could anyone please explain how this for loop is executing?
That for loop is a classic idiom for a non-terminating loop. It's what you use when you want a loop that never terminates, or whose termination is controlled by control flow statements inside the loop. The latter is the case here.
for(;;)
All parts of the for loop are empty. They key to understanding why it is a non-terminating loop is the empty controlling expression in the for statement.
The standard (6.8.5.3 The for statement) says, with my emphasis:
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.158)
Both clause-1 and expression-3 can be omitted. An omitted
expression-2 is replaced by a nonzero constant.
And this means that your loop will never terminate due to the controlling expression part of the for statement.
for(;;)
is a for loop which performs no initialisation, has no exit condition and performs no post-action.
It will loop forever unless code inside the loop contains a condition that can result in break being called.
Your loop is equivalent to
int i,j;
for(i=1, j=1 ;i<=5 ;i+=j) {
j+=i;
printf("%d\n",j);
}
for(;;) is equivalent to while(true) (or while(1) in old-school C), both of whose terminations are only controlled by the statements inside them.
Edit:
To rehash a couple of old jokes (borrowed from here):
Don't use for (;;) {} — it makes the statement cry.
Unless, of course, you #define EVER ;;.
for(i=0; 0; i)
{
//statement
}
Why the statement executes only one time ? Either it does not execute the statement or the statement should go into an infinite loop. but the statement executes just one time. Can you please help me.
Make sure you don't have a semi-colon after the for loop otherwise the compiler will take the semi-colon to be the end of the loop and anything in the following braces will be executed once.
for(i=0; 0; i); // end of loop
{
// do something once
}
You don't have a semicolon in your example but I've seen people do this often in programming courses and the fact it runs once is a symptom of this mistake. Just a suggestion.
Actually, that line will not execute the statement. I would look at your program again to see if some other output / statements have been misidentified as the output of the statement in the block
#include <stdio.h>
int main(int argc, char** argv)
{
int i;
for (i = 0; 0; i) {
printf("i is %d\n", i);
}
return 0;
}
when ran yields no output.
Another possibility is that your source code is now out-of-sync with your binaries, something that happens occasionally with hand rolled C build systems. Try removing your .o object files, your generated binaries, and recompiling from scratch. If the execution disappears, perhaps you need to look at how you achieve your build a bit more carefully.
This is quote from the C99 standard about the for loop:
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. If clause-1 is a
declaration, the scope of any variables 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.134)
Since the condition is false, it shouldn't execute it even once. So it's clearly a bug in the compiler you use.
Try
for (i = 0; i < 10; i++)
then lookup the for loop on google.
There are three parts to a for loop
initialization ; loop end condition ; increment.
why your code says, is probably not what you mean.
This loop will not execute even one time because the terminating condition is 0 ie false
for(i=0; 0; i)
{
printf("%d",&i)
}
Does not print any thing.
I came across the following question :
How many times will the following for loop run -
for(;0;)
printf("hello");
I executed and it runs 1 time . I am not able to understand how?
This will not execute even for 1 time. I guess you have a bad compiler?
Ok. I think you are using Turbo C ;-)
EDIT:
From C99 standard:
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. If clause-1 is a
declaration, the scope of any variables 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.134)
It clearly states that condition is evaluated first before executing the loop. Any standard conforming compiler should not execute the loop for(;0;) {} even once.
Either the code you copied here is not really what is in your .c file or you have a buggy compiler.
Maybe you have an additional semicolon?: for(;0;); printf("!"); will print once.
for loops are defined as:
for(startExpression; testExpression; countExpression)
{
block of code;
}
startExpression is evaluated before the code;
testExpression is evaluated before the code;
countExpression is evaluated after code;
Decoding:
for(;0;)
Means
no startExpression
testExpression evaluated to false, therefore loop exits.
Edited to show correct for loop decoding.
The code as written above will never enter the for loop.
Check the code on ideone link.
My be this not what you have in your souce code, you probably typed a ; after for without noticing it like this:
for(;0;);
printf("hello");
In that case your program will print "hello".
Since the expression is 0, it is taken to be false. So, in this case the loop runs 0 times.