why this for loop goes in infinite loop executation? - c

see i have one code like this
int main () {
uint32_t i ;
for(i=4;i>=0;i--)
printf("i is %d \n",i);
return 0;
}
it goes in infinite loop.
why i's value goes below 0 & still loop is going to executive?

uint32_t means unsigned integer and so its value is always >= 0 - thus your loop executes infinitely.
Note that many compilers will issue a warning indicating that i>=0 comparison is always true.

You see negatives values in your printf because you print it as %d, but in the condition, the uint32_t is always positive (you are doing an overflow).

You are using uint32_t means unsigned and then checking the condition in for loop that i >= 0 so when the loop executes for value i = 0 and then it makes the i = -1 but i is unsigned so it will make the value of i INT_MAX(what ever your system supports). so and still the value is greater than 0 so condition is true.
And the answer for how it prints the negative values for i is that, you are using the '%d' that is for signed.
If you want to see the result you can use the '%u' option so it will print the original unsigned value of i.
If you want the result that you want from the program then try to cast the uint to int at the time of condition checking.

Related

Unsigned vs Signed Integer [duplicate]

This question already has answers here:
Why does counting down an unsigned int loop forever in C?
(5 answers)
Closed 4 years ago.
What's wrong with this code?
#include<stdio.h>
int main()
{
unsigned int i;
for(i=100;i>=0;i--)
{
printf("%u ",i);
}
return 0;
}
This code doesn't work but if i use for(i=100;i>0;i--) then it works!
or another way is to use integer instead of using unsigned integer.
An unsigned int can never be negative, so i >= 0 holds true all the time. So, it is effectively an infinite loop.
Since variable i is declared as unsigned int, this condition i>=0 never fails, hence results in infinite loop rotation.
unsigned int i;
for(i=100;i>=0;i--) { /* i will never become negative */
printf("%u \n",i);
}
Note that UINT_MAX is 4294967295 see this i.e it ranges from 0 to 4294967295 so when i=0 it prints & gets decremented, next it won't be -1, it will be 4294967295, hence above for loop results in infinite loop.
another way is to use integer instead of using unsigned integer ? you can do the same using unsigned integer also by replacing the condition part as i>0 so that when i=0 it fails & comes out of loop.
What's wrong with this code?
i>=0 is always true as i is unsigned. Then for(i=100;i>=0;i--) loops forever.
To continue using unsigned i:
Since the coding goal always wants to enter the loop at least once, instead of testing the loop condition in the begining, test at the end.
//for(i=100;i>=0;i--) {
// printf("%u ",i);
//}
i = 100; // or any unsigned constant.
do {
printf("%u ",i);
} while (i-- > 0);
another way is to use integer (int) instead of using unsigned integer (unsigned).(?)
Use int. Of course this will not work if i needs to start at values greater than INT_MAX. If such large values are needed, consider a wider signed type like long long.
int i;
for(i=100;i>=0;i--) {
printf("%u ",i);
}

Why this piece of code results infinite loop

unsigned int i = 1<<10;
for(; i>=0; i--) printf(ā€œ%d\nā€, i);
Can anyone please explain the reason why this code results in infinite loop? Thanks in advance for any response.
Unsigned int - its always interpreted as >= 0
Unsigned integers are always positive. When i == 0 and you decrement 1 from it, result will wrap-around to maximum unsigned int value UINT_MAX, because your data type cannot handle negative values.
Reason why it results in an infinite loop is already explained by other answers. However to achieve the intended behaviour of your code, counting down from 1024 to 0 using unsigned int, try this instead.
unsigned int i = (1<<10)+1;
for(;i-- > 0;) printf(ā€œ%d\nā€, i);
Note that the value of i after the loop will be the rolled over value.

Explain the result of the program?

The output of below c program is,
output : 1,2,3,4 ........ 126,127,-128,-127 .... -2,-1 ?
#include <stdio.h>
#include <string.h>
int main()
{
char i=0;
for(i<=5 && i>=-1 ; ++i;i>0)
printf("%d\n",i);
printf("\n");
return 0;
}
please explain why is so ?
Here is a breakdown of your code, it's fairly sneaky:
for( i <= 5 && i >= -1 ; ++i; i > 0)
Typically a for-loop is, ( initial statement, expression, second statement ). Looking at your code before the first null statement: what you have done is an expression (in place of a statement), which does not matter at all however it's entirely useless. So removing that line (which has no effect on the result of this expression) gives us:
for( ; ++i; i > 0)
... now if you noticed you initialized i to be 0 before the for loop. What you are doing next is incrementing i and then returning its value (see here), and hence it will go from 1 ... -1 (overflowing at 127). This is because in C any non-zero value is true and 0 is false. Hence, once i becomes 0 it will stop running the loop. i can only become zero by overflowing.
Your third statement does not matter, it's irrelevant.
It is called overflow. Type "char" uses 1 byte of your RAM's capacity, so it can store only 256 values. These are [-128, 127]. When you try to get over 127, it will get back the the lowest value.
Other than that, your for loop is a little messed up. Try
for ( i = 0 ; i <= 5 ; ++i ) // This will print 0,1,2,3,4,5
printf( "%d\n" , i );
I'm guessing you're using the for loop incorrectly.
for(i<=5 && i>=-1 ; ++i;i>0)
The above code means:
Before anything, evaluate i<=5 && i>=-1 (which doesn't have any side effects so nothing happens)
On every iteration, increment i then check if it is zero. If it is non-zero, run another iteration.
At the end of every iteration, evaluate i>0 (which again, does nothing).
Therefore, your loop simplifies down to and is essentially
while (++i)
To explain your result, the system you're using is likely using implements a char as a signed two's complement integer which 'wraps' to a negative number when it is higher than 127 (since 128 in a 8 bit two's complement integer is a -128)
First of all, char occupies 1 byte and it is signed.
With the help of 8 bits (1 byte) the range of numbers that you can represent is
**-(2^(8-1)) to +((2^(8-1)) -1) [ie from -128 to +127].**
In your code you are incrementing i and also printing the same.
once i reaches 127 (in binary 0111 1111 = 127) and you again increment it becomes (1000 0000) which is -128.
And while printing you are using %d. so out will be in integer format.
That is why it is printing 1,2,3 ... -128, -127...
If you didn't understand how 1000 0000 is -128, read
What is 2's Complement Number?
Because this:
for(i<=5 && i>=-1 ; ++i;i>0)
works out as
1) Initialisation:
i<=5 && i>=-1
does nothing
2) Termination condition:
++i
increments i and will terminate when i gets to zero
3) statement executed each time round loop (normally an increment / decrement):
i > 0
does nothing.
So your code loops from i = 0 back till it's zero again

Understanding the exit condition of a 'for' loop

I had this question after reading the Stack Overflow quesion Print an int in binary representation using C.
In a user's comment, they posted this for loop, which assigns either a 1 or a 0 to the bit position in order to convert from an int decimal to char * binary.
for(; bits--; u >>= 1)
str[bits] = u & 1 ? '1' : '0';
I understand why there doesn't need to be an initialized value. This is the syntax for a for loop that I've always known:
for ( variable initialization; condition; variable update )
I don't understand how 'bit--' can be an exit condition. Please help me understand how this code works (I tested it, and it is valid).
In C, a value of zero evaluates to "false" in a Boolean context. So when bits-- evaluates to 0, in the context of the loop it evaluates to "false" and terminates the loop.
If you say, for example:
int x = 1;
if (--x)
{
printf("True!\n");
}
else
{
printf("False!\n");
}
It will output "False", because --x evaluates to 0, which is "false" in a Boolean context.
All conditions basically boil down to checking whether something is 0 or not. 0 means false, everything else means true. So that loop will break when bits is 0.
You will sometimes see while or if conditions written
if (variable) // or while(variable)
That is just shorthand for
if (variable != 0) // or while (variable != 0)
So
for (; bits--; u >>= 1)
is short for
for (; bits-- != 0; u >>= 1)
bits-- is an assignment expression of type int (since it will return the value of b, which is int). To match the for loop syntax, it gets converted to a Boolean expression, which means it is true if bits != 0.
In fact, the condition is identical to bits!=0, but by using bits--, it changes the value of bits at the same time, making the code more compact. That's all.
As others said, in C, you can use integers as a condition - 0 or false, and anything else for true. (Actually, you almost always do it - even an expression like a<b is an int.)
So, the loop will end when bits-- will be 0.
When the -- operator comes after the variable, it decreases the variable, and gets the previous value of it. For example, if you have int a=3,b; b=a--;, then b will be 3, and a will be 2.
So, the loop will exit after that bits will been decreased from 0 to -1.
That means that, if in the beginning, bits==8 (for example), the loop will iterate 8 times, when in the first, bits will be 7 (because the condition had checked), and in the last, bits will be 0. It is a nice way to loop through an array (Since in C, an array of bits variables is being indexed from 0 to bits-1).

For loop condition to stop at 0 when using unsigned integers?

I have a loop that has to go from N to 0 (inclusively). My i variable is of type size_t which is usually unsigned. I am currently using the following code:
for (size_t i = N; i != (size_t) -1; --i) {
...
}
Is that correct? Is there a better way to handle the condition?
Thanks,
Vincent.
Yes, it's correct and it is a very common approach. I wouldn't consider changing it.
Arithmetic on unsigned integer types is guaranteed to use modulo 2^N arithmetic (where N is the number of value bits in the type) and behaviour on overflow is well defined. The result is converted into the range 0 to 2^N - 1 by adding or subtracting multiples of 2^N (i.e. modulo 2^N arithmetic).
-1 converted to an unsigned integer type (of which size_t is one) converts to 2^N - 1. -- also uses modulo 2^N arithmetic for unsigned types so an unsigned type with value 0 will be decremented to 2^N - 1. Your loop termination condition is correct.
Just because for has a convenient place to put a test at the beginning of each iteration doesn't mean you have to use it. To handle N to 0 inclusive, the test should be at the end, at least if you care about handling the maximum value. Don't let the convenience suck you in to putting the test in the wrong place.
for (size_t i = N;; --i) {
...
if (i == 0) break;
}
A do-while loop would also work but then you'd additionally give up i being scoped to the loop.
You can use this:
for (size_t i = n + 1; i-- > 0;)
{
}
Hope that helps.
Personally, I would just use a different loop construct, but to each their own:
size_t i = N;
do {
...
} while (i --> 0);
(you could just use (i--) as the loop condition, but one should never pass up a chance to use the --> "operator").
for ( size_t i = N ; i <= N ; i-- ) { .... }
This would do it because size_t is an unsigned int. Unsigned ints are 32bits. When the variable i has a value of 0, you want your loop to execute the condition. If you perform i--, the computer does
00000000000000000000000000000000
-00000000000000000000000000000001
Which results in a clear overflow, giving a value of 111111111...1. For a signed two's complement integer, this value is clearly negative. However, the type of i is an unsigned int so the computer will interpret 111111...1 to be a very large positive value.
So you have a few options:
1) Do as above and make the loop terminate when overflow occurs.
2) Make the loop run from i = 0 to i <= N but use (N-i) instead of i in everywhere in your loop. For example, myArray[i] would become myArray[N-i] (off by one depending on what the value of N actually represents).
3) Make the condition of your for loop exploit the precedence of the unary -- operator. As another user posted,
for ( size_t i = N + 1 ; i-- > 0 ; ) { ... }
This will set i to N+1, check to see if the condition N+1 > 0 still holds. It does, but i-- has a side effect, so the value of i is decremented to i = N. Keep going until you get to i = 1. The condition will be test, 1 > 0 is true, the side effect occurs, then i = 0 and it executse.
You can use a second variable as the loop counter to make the range of iteration clear to a future reviewer.
for (size_t j=0, i=N; j<=N; ++j, --i) {
// code here ignores j and uses i which runs from N to 0
...
}
for (i=N; i+1; i--)
Since unsigned integer will roll into its max value when decremented from zero, you can try the following, provided N is less then that maximum value (someone please correct me if this is UB):
for ( size_t i = N; i <= N; i-- ) { /* ... */ }

Resources