Understanding the exit condition of a 'for' loop - c

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).

Related

Why does this create an infinite list of negative odd numbers?

Why does the following instruction create an infinite list of negative numbers (-1, -3, -5, ...) if i=1?
while (i--)
printf("\n%i", --i);
i = 1 // 1
while (i--) // value of 'i--' is 1 is true; side-effect i = 0
printf("\n%i", --i); // print value of '--i' ie -1, side-effect i = -1
while (i--) // value of 'i--' is -1 is true; side-effect i = -2
printf("\n%i", --i); // print value of '--i' ie -3, side-effect i = -3
while (i--) // value of 'i--' is -3 is true; side-effect i = -4
printf("\n%i", --i); // print value of '--i' ie -5, side-effect i = -5
...
Note that side-effect above may occur before or after (or even during) the evaluation of rest of the expression.
There is nothing special. You have negative number of i, which is equal to 1 at the beginning (and then -1,-3,-5,...) because you decrement variable i two times. First, you are doing it in conditional expression: "while(i--)". After it, it happens in while block of code: "printf("\n%i", --i);". Finally, it continues again and again decreasing by 2 since you are using while loop.
The reason is i-- is a post decrement operator. Meaning, the value of i is used in expression followed by the evaluation of the expression itself. This causes the value of i in your comparison to different from the one present in the print statement which makes the infinite loop.
i-- Post decrement operation which tells that the value be used
first followed by the expression evaluation.
--i pre decrement operation which tells that the expression be
evaluated first followed by using the result of the expression.
On each iteration, i decrements 2 times, which is making series 1, -1, -3, and so on. Always positive values which lead to an infinite loop. If you choose i=2 then series will be 2, 0 and that's all. After getting zero while the loop will get exit.
Because you substract 2 from the odd number two it will never be zero on most implementations.
while (i--)
if(i & 1) printf("\n%i", i);
will stop at some point.
The while condition uses post-decrement. That means it tests the original value of i, which is 1, and then decrements the value to 0. Since 1 is truthy, it goes into the loop.
Inside the loop, you print --i. This is pre-decrement, so it sets i to -1, and prints that value.
On the next iteration the same thing happens. It tests -1, which is truthy, decrements it to -2, enters the loop body, decrements it to -3, and prints that.
Eventually your code will run into undefined behavior when i overflows below the smallest negative number. In most implementations it will wrap around and continue the same progression, but the actual behavior is not specific by the language.
i seems to be of type int and is with that a signed integer which also covers a negative range.
The standard mandates that an int needs to be capable to represent at least a range of −32767 to 32767.
If you decrement it, the value can go down to INT_MIN.
If you decrement the value after it has been reached the border of INT_MIN, the behavior is undefined.
i is decremented by 2 in each iteration, so the output shows a decrease in 2er steps.
If the loop is infinite is dependent upon how the implementation treats a decrementation after INT_MIN.
The while condition is always true as long as i is non-zero, which is the case here as i is decremented by 2 at the first iteration and there as well thereafter i is negative.

Puzzled about for loops in C

Just to be clear, I understand how for loops work. However, the different syntax causes me problems... Let me give you an example:
I was looking up a recursive sorting algorithm (insertion sort). The code went like this:
void insertion_recursive(int array[],int size){
int i;
if (size<=1) return;
insertion_recursive(array,size-1);
for(i=size-1;i;i--)
if(array[i]<array[i-1])
swap(&array[i],&array[i-1]);
else
break;
}
I understand how the code works, but the condition for the loop is confusing me:
for(i=size-1 ; i ; i--)
What does it mean? Just leaving 'i' without specifying a condition?
An expression represents a single data item--usually a number. The expression may consist of a single entity, such as a constant or variable, or it may consist of some combination of such entities, interconnected by one or more operators. Expressions can also represent logical conditions which are either true or false. However, in C, the conditions true and false are represented by the non-zero integer values and zero integer value, respectively. Several simple expressions are given below:
a + b
x = y
t = u + v
x <= y
++j
In your example, i is an expression whose value is expression's l-value which is in this case, it is the value of variable i.
The expression will evaluate to true for non-zero i values and false if value of i is zero.
So, for(i=(size-1); i ; i--) is equivalent to for(i=(size-1); i != 0; i--).
In C when trying to evaluate a condition, everything that is 0 is false, and everything else is true.
Even pointers are treated the same way. The constant NULL is actually defined as 0. In C++11 we finally have the null_ptr for type safety.
In C there is no bool type, and in C++ if you cast true to integer you get 1, and false casts to 0.
i by itself is converted to a boolean, similar to if (i) {...} or if (! i) {...}; integers are considered true when nonzero and false when zero.
So, for(i=size-1 ; i ; i--) is equivalent to for(i=size-1 ; i != 0; i--).

Need a simple help in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Can anyone tell me how does this code work?
int Calc(int *arr, int m)
int result;
for (result &= 0; m; (arr[--m] & (0x1 << 0x1F)) ? result += arr[m]: Void());
return result;
I can't understand for loop:/
Where did you find this code so I can hunt that person down and beat him with a copy of Schildt?
It's no surprise you don't understand the loop; it wasn't written to be understandable. The only place this kind of code is acceptable is the IOCCC, except it's not obfuscated enough for that competition.
Taking each bit in turn:
result &= 0;
is a really funky way of initializing result to 0; it's shorthand for result = result & 0, which performs a bitwise-AND of result against 0 (giving 0) and assigns the result back to result. It's also unsafe, since an uninitialized object may contain a trap representation. That should have been written as simply result = 0.
m;
just checks the current value of m; the loop will run until it is 0. The loop basically starts at the last element and works its way down to the first.
(arr[--m] & (0x1 << 0x1F)) ? result += arr[m]: Void()
Ugh. So, the first thing it does is take the value of the array at index m-1 and does a bitwise and against 0x1 << 0x1F (1 shifted left 31 postitions, or essentially 0x80000000); if the result of this operation is non-zero, then we add the value of that array element to result, otherwise we execute some incredibly inappropriately named function that hopefully returns a 01. Given that we're dealing with signed integers, and that on most platforms an int is 32 bits wide, this code is obviously adding up negative values in result.
A slightly saner way of writing that would be
result = 0;
while ( m ) // or m != 0, or m > 0, whatever you prefer
{
if ( arr[--m] < 0 )
result += arr[m];
}
1. The conditional operator ?: isn't meant to be used as a control structure like this. The syntax is expr1 ? expr2 : expr3. First, expr1 is evaluated and all side effects applied; if it results in a non-zero value, then the result of the expression is expr2; otherwise, the result is expr3.
Part 1
Firstrly result &= 0 is used for setting 0 to result variable using bitwise AND operation. Bitwise with 0 will ever return 0.
You can write it simply this way: result = 0
The better (much optimal) way of doing this is: result ^= result. (Bitwise XOR)
Part 2
This loop will iterate while m is greater (or less) than 0. Because m expression will return true if m != 0.
Much secure way of doing it is m > 0.
Also you can use this expression, which is not making programm much optimal, but it will be cleaner to another programmer to understand your code: !!m (casting m variable to bool), which is equal to m != 0;
Part 3
In this part ternary operator (logical_expression ? expression_1 : expression_2) is used.
If logical_expression is true, then expression_1 will be executed, expression_2 will be executed otherwise.
So in your code, if this expression (arr[--m] & (0x1 << 0x1F)) returns true then we add arr[m] to result variable. And do nothing in another case.
Also m variable is decremented in ternary logical expression (arr[--m]).

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.

why does this print? (C language)

Why does the following code run the while loop? I thought "mid = term" is an assignment, not a condition? Please explain. Thanks.
#include <stdio.h>
main ()
{
int mid = 4, term = 4;
while ( mid = term)
printf("%d\n", --term);
}
The result of an assignment is the value. Therefore the expression evaluates to 4 or a non-zero and thus, in C, TRUE.
mid = term is an expression evaluating to term. So the while loop will run till term = 0.
Because the expression evaluates to true.
Basically, you are saying mid = 4
Since any int that isn't zero, returns true in a conditional statement - the while will loop.
The expression mid = term actually evaluates to the value of mid after assignment. So, what's being evaluated is while(4). Since all nonzero integers are interpreted as true (this is kind of a simplification), the while loop will run as long as term != 0.
Both the assignment and the test happen in the "while" loop, so the printf() executes four times in this case.
Assignment are also expressions which hold a value: the value they assign. mid=0 is an expressions that evals to 0 (thus false).
You assign term to mid and then test the truth of mid. mid is truthy whenever it is non-zero. The loop terminates when term (and hence mid) has been decremented to equal 0, which is falsy.
You are assigning the value of term to mid, then the while checks the value of mid which evaluates to true, until it reaches 0.
This should output:
3
2
1
0

Resources