Why an expression instead of a constant, in a C for-loop's conditional?
Solution 1:
Yes, they are equivalent in behavior.
Then why do people use the (1 << 7) version?
I guess, they use it to document it is a power of 2.
Calculating the condition every time must be an overhead! I am unable to find the reason behind this!
Not really, any normal compiler will replace 1 << 7
by 128
and so both loops will have the same performances.
(C11, 6.6p2) "A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be."
Solution 2:
Let's translate each one of these options into plain English:
for(i = 0; i < (1 << 7); i++) // For every possible combination of 7 bits
for(i = 0; i < 128; i++) // For every number between 0 and 127
Runtime behavior should be identical in both cases.
In fact, assuming a decent compiler, even the assembly code should be identical.
So the first option is essentially used just in order to "make a statement".
You could just as well use the second option and add a comment above.
Solution 3:
1 << 7
is a constant expression, the compiler treats it like 128
, there's no overhead in run time.
Without the loop body, it's hard to say why the author uses it. Possibly it's a loop that iterates something associated with 7 bits, but that's just my guess.
Solution 4:
Then why do people use the (1 << 7) version?
It is a form of documentation, it is not a magic number but 2^7
(two to the seventh power) which is meaningful to whomever wrote the code. A modern optimizing compiler should generate the exact same code for both examples and so there is no cost to using this form and there is a benefit of adding context.
Using godbolt we can verify this is indeed the case, at least for several versions of gcc
, clang
and icc
. Using a simple example with side effects to ensure that the code is not totally optimized away:
#include <stdio.h>
void forLoopShift()
{
for(int i = 0; i < (1 << 7); i++)
{
printf("%d ", i ) ;
}
}
void forLoopNoShift()
{
for(int i = 0; i < 128; i++)
{
printf("%d ", i ) ;
}
}
For the relevant part of the code we can see they both generate the following see it live:
cmpl $128, %ebx
What we have is an integer constant expression as defined in the draft C11 standard section 6.6
Constant expressions which says:
An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants,[...]
and:
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.115)
and we can see that a constant expression is allowed to be evaluated during translation:
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.