#include void main() { int i=1; for...">

What is the value of "i" after the end of the loop. It is always zero. What for?

#include<stdio.h>
#include<conio.h>
void main()
{
    int i=1;
    for(;i;)i++;
    printf("%d",i);
    getch();
}

      

I always get the output as zero, no matter what the value is i

.

+3


source to share


5 answers


Based on your for loop, "i" is the termination condition. In C, any nonzero value is considered true when used in a boolean expression. So the only exit condition for the loop you've done is a situation where i finally becomes null, which, as others have noted, is probably due to what happened when the value i overflowed. Again, as others have pointed out, this particular behavior is compiler specific and overflow does not always result in a workaround, as this is essentially undefined behavior.



+2


source


TL; DR: your program prints 0

because if the loop ever exits, it must be because it i

is zero; and starting from i = 1

this can happen, for example with an integer overflow causing a traversal. But the C standard does not actually require such a traversal, and hence the code invokes undefined behavior. An optimizing compiler can, and probably will, make the resulting program do funny things.


The cycle for

can be exchanged with the next cycle while

- they are the same.

while (i) {
    i++;
}

      

This means: "while i

nonzero, increment i

by one". After the loop exists, the value i

should be zero, and that's what is printed.

However, the initial value i

is 1. What happens to print 0 is just coincidence, because your program is causing undefined behavior : each iteration, you increment it by 1. By the time it becomes INT_MAX

and you add 1 to it, the behavior is undefined because it INT_MAX + 1

cannot be represented in int

.

Then anything can happen, including wrap around the counter before INT_MIN

, which seems to be happening with your unoptimized program. However, this is not required. The compiler could generate code that would make the loop hang there forever, for example. This is not just hypothetical, but easily obtained with GCC 6.3.0 :

% gcc wraparound.c -O2
wraparound.c: In functionmain’:
wraparound.c:6:14: warning: iteration 2147483646 invokes undefined behavior 
           [-Waggressive-loop-optimizations]
     for(;i;)i++;
             ~^~
wraparound.c:6:5: note: within this loop
     for(;i;)i++;
     ^~~

      

The resulting program never ends, and it never prints anything .

Disassembly reveals that the only command in main

:

0000000000000530 <main>:
 530:   eb fe                   jmp    530 <main>

      

That is, the code starts an infinite loop, i.e. while (1) {}

...




If - for whatever reason - it wraps up to INT_MIN

and execution continues, then eventually negative INT_MIN

will increment the required 2 billion times for it to become 0, and then the termination condition i

evaluates to 0, which is false, and the loop ends. And since i

it matters 0

now, what is printed.

Integer overflow is also used as the only example in C standard 3.4.3 of undefined behavior :

undefined behavior

  • when using a non-portable or erroneous program or erroneous data for which this International Standard imposes no requirements

  • NOTE. Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, behaving during translation or program execution in a documented manner (with or without issuing a diagnostic message) to stopping translation or execution (with issuing a diagnostic message).

  • EXAMPLE An example of undefined behavior is behavior on integer Overflow.


Signed integer overflow is not defined by the C standard, but unsigned integer math is guaranteed to complete. Your code will be fully qualified if you change int i = 1;

to unsigned int i = 1;

. Although it may take you a while if unsigned int

is 64 bit and you haven't optimized.

This program

#include <stdio.h>
int main(void)
{
    unsigned int i = 1;
    for(;i;)i++;
    printf("%d\n",i);
}

      

when compiled with my GCC using, -O2

unrolls the loop completely and immediately outputs 0:

% time ./a.out
0
./a.out  0.00s user 0.00s system 0% cpu 0.003 total

      

i.e. the compiler dumped the result and encoded it.

+5


source


I have a condition in for (; i;) so it gets converted to boolean and checked:

  • i test positive to true
  • i = 0 result in false

so the loop will run until it reaches its maximum possible value and overflows and becomes 0, when it does, it ends to complete and you print the value i (i.e. 0).

The change to the initialization i in the beginning doesn't matter, because every non-zero value will be converted to true, so for will run anyway and run like I said earlier, unless you initialize it to 0.

I don't understand what you want to accomplish with this code, but I hope my answer helps

0


source


Cycle

for(;i;)
  i++;

      

basically says "while is i

not zero, increment i

". An integer overflow of 1 occurs and i

eventually completes to 0, after which the loop is terminated. This is the value you are printing.


  1. Signed integer overflow behavior is undefined, so it is not strictly guaranteed i

    to wrap around zero or that the loop will end; however, in most real world systems, it will eventually fall back to 0.
0


source


Loop code:

   int i=1;
     for(;i;)i++;
      printf("%d",i);

      

Initializes i to 1, then the loop for

continues incrementing i until it is zero, and then exits and prints the value of i, which should be zero.

Why?

A for

has four parts to its syntax for(init;test;increment) body;

:

  • init

    : this is usually used to initialize some counter for example i

    , but in your case it's empty so it doesn't do anything. Fortunately, you initialized i

    in the previous statement, but it's best to do it in a loop for

    .
  • test

    : this is used to break out of a loop by testing some expression to see if it is zero. When it evaluates to zero (or false if it is a boolean expression) then the loop ends. In your case, you are testing i

    , so the loop will keep incrementing i

    until it is zero, then the for loop will exit. This is why you only see print when i

    it goes to zero.
  • increment

    : is usually placed here i++

    , which you place as body instead. Body
  • body

    : In your case, the body i++

    . You might be thinking what printf

    is part body

    is the next statement after the loop for

    . To include it in a loop, you will need to add curly braces (unlike Python, which uses indentation to parse the syntax).

    int i = 1; for (; i;) {i ++; E ("% d", i); }

With printf included in the loop as shown above, you will see that your loop will keep incrementing i until it reaches MAX_INT, and then thanks to the 2s complement, it will roll over to -INT_MAX (actually INT_MIN) and keep incrementing until it equals zero. As others have noted, counter overflow is technically undefined behavior, but the wrapper is what I've seen in every architecture I've used with C, but being UB, your loop shouldn't depend on that wrapper in a specific order. It also makes complex code difficult to understand and maintain!

As written, your loop grows i

roughly 4 billion times (depending on the size int

on your computer), but on the credit of the C compiler, this is very fast. Once added printf

to your cycle, it will take significantly longer.

The correct way to write a loop is:

#include<stdio.h>
#include<conio.h>
void main()
{
    int i;
    for(i=1; i!=0; i++)
    {
       printf("%d",i);
       getch();
    }
}

      

0


source







All Articles