Why this piece of code results infinite loop - c

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.

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);
}

Proper way to count down with unsigned

I am reading Carnegie Mellon slides on computer systems for my quiz. In the slide page 49 :
Counting Down with Unsigned
Proper way to use unsigned as loop index
unsigned i;
for (i = cnt-2; i < cnt; i--)
a[i] += a[i+1];
Even better
size_t i;
for (i = cnt-2; i < cnt; i--)
a[i] += a[i+1];
I don't get why it's not going to be infinite loop. I am decrementing i and it is unsigned so it should be always less than cnt. Please explain.
The best option for down counting loops I have found so far is to use
for(unsigned i=N; i-->0; ) { }
This invokes the loop body with i=N-1 ... 0. This works the same way for both signed and unsigned data types and does not rely on any overflows.
This loop is simply relying on the fact that i will be decremented past 0, which makes it the max uint value. Which breaks the loop because now i < cnt == false.
Per Overflowing of Unsigned Int:
unsigned numbers can't overflow, but instead wrap around using the
properties of modulo.
Both the C and C++ standard guarantee this uint wrapping behavior, but it's undefined for signed integers.
The goal of the loops is to loop from cnt-2 down to 0. It achieves the effect of writing i >= 0.
The previous slide correctly talks about why a loop condition of i >= 0 doesn't work. Unsigned numbers are always greater than or equal to 0, so such a condition would be vacuously true. A loop condition of i < cnt ends up looping until i goes past 0 and wraps around. When you decrement an unsigned 0 it becomes UINT_MAX (232 - 1 for a 32-bit integer). When that happens, i < cnt is guaranteed to be false, and the loop terminates.
I would not write loops like this. It is technically correct but very poor style. Good code is not just correct, it is readable, so others can easily figure out what it's doing.
It's taking advantage of what happens when you decrement unsigned integer 0. Here's a simple example.
unsigned cnt = 2;
for (int i = 0; i < 5; i++) {
printf("%u\n", cnt);
cnt--;
}
That produces...
2
1
0
4294967295
4294967294
Unsigned integer 0 - 1 becomes UINT_MAX. So instead of looking for -1, you watch for when your counter becomes bigger than its initial state.
Simplifying the example a bit, here's how you can count down to 0 from 5 (exclusive).
unsigned i;
unsigned cnt = 5;
for (i = cnt-1; i < cnt; i--) {
printf("%d\n", i);
}
That prints:
4
3
2
1
0
On the final iteration i = UINT_MAX which is guaranteed to be larger than cnt so i < cnt is false.
size_t is "better" because it's unsigned and it's as big as the biggest thing in C, so you don't have to ensure that cnt is the same type as i.
This appears to be an alternative expression of the established idiom for implementing the same thing
for (unsigned i = N; i != -1; --i)
...;
They simply replaced the more readable condition of i != -1 with a slightly more cryptic i < cnt. When 0 is decremented in the unsigned domain it actually wraps around to the UINT_MAX value, which compares equal to -1 (in the unsigned domain) and which is greater than or equal to cnt. So, either i != -1 or i < cnt works as a condition for continuing iterations.
Why would they do it that way specifically? Apparently because they start from cnt - 2 and the value of cnt can be smaller than 2, in which case their condition does indeed work properly (and i != -1 doesn't). Aside from such situations there's no reason to involve cnt into the termination condition. One might say that an even better idea would be to pre-check the value of cnt and then use the i != -1 idiom
if (cnt >= 2)
for (unsigned i = cnt - 2; i != -1; --i)
...;
Note, BTW, that as long as the starting value of i is known to be non-negative, the implementation based on the i != -1 condition works regardless of whether i is signed or unsigned.
I think you are confused with int and unsigned int data types. These two are different. In the int datatype (2 byte storage size), you have its range from -32,768 to 32,767 whereas in the unsigned int datatype (2 byte storage size). you have the range from 0 to 65,535 .
In the above example mentioned, you are using the variable i of type unsigned int. It will decrements up to i=0 and then ends the for loop as per the semantics.

Min/Max Value of a short int in C

PROBLEM SOLVED: It still doesn't work on Code::Blocks so it has something to to with Codeblocks.
I have a Problem with the following C-Code. It is supposed to show the max/min Value of a "short int". I'm pretty sure it is right but it doesn't seems to work on my machine.
As the output I just get a zero instead of the desired +32767 and -32768.
If someone could verify for me that it is indeed not a problem in the code but a problem with my software.
PS: I tried running the code on someone else's machine and it worked fine there.
#include <stdio.h>
int main()
{
short int si=0;
short int si_pred=0;
while (si>=0) {
si_pred=si;
si++;
}
printf("%d lowest possible value for a short int.\n",si);
printf("%d highest possible value for a short int.\n",si_pred);
return 0;
}
Your while loop is terminating early because you set si to 0, and your loop will only run when si > 0. Try this, since you know that the largest int should be at least 1:
short int si = 1;
Now your loop won't short-circuit, since 1 > 0.
Or, even better, just set the loop condition to check for si >= 0.
while(si >= 0) {
si_pred = si;
si++;
}
The problem isn't Code::Blocks. The problem is that the behavior on signed integer overflow is undefined. You're not going to get consistent results from compiler to compiler, because there's no requirement on the compiler to handle signed integer overflow in any particular way. There's no guarantee that adding 1 to SHRT_MAX will result in SHRT_MIN.
The right way to do this is to include "limits.h" in your source code and examine the values of SHRT_MIN and SHRT_MAX.

why this for loop goes in infinite loop executation?

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.

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