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.