Why is an expression instead of a constant in C for-loop conditional?

In many programming competitions, I saw people write this type of for -loop

 for(i = 0; i < (1 << 7); i++) 

If I'm missing something, it's the same as

 for(i = 0; i < 128; i++) 

Why use the version (1 << 7) ?
Doesn't calculate the condition every time there is unnecessary overhead?

+57
c coding-style for-loop expression constantfolding
Aug 30 '14 at 11:58
source share
7 answers

Yes, they are equivalent to behavior.

Then why do people use the version (1 <7)?

I think they use it for documentation, this is power 2.

Calculating a condition every time should be an overhead! I can not find the reason for this!

In fact, no ordinary compiler will replace 1 << 7 with 128 , and therefore both loops will have the same characteristics.

(C11, 6.6p2) "A constant expression can be evaluated at translation time and not at runtime, and, accordingly, can be used anywhere where a constant can be."

+76
Aug 30 '14 at 12:03 on
source share

Translate each 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 

In both cases, the execution behavior should be the same.

In fact, assuming a decent compiler, even the assembly code should be identical.

So, the first option is essentially used only to โ€œmake an expressionโ€.

You can simply use the second option and add a comment above.

+31
Aug 30 '14 at 12:23
source share

1 << 7 is a constant expression, the compiler treats it as 128 , there is no overhead at runtime.

Without the body of the cycle, it is difficult to say why the author uses it. Perhaps this is a loop that repeats something related to 7 bits, but this is just my guess.

+19
Aug 30 '14 at 12:04 on
source share

Then why do people use the version (1 <7)?

This is a form of documentation, this is not a magic number, but 2^7 (from two to seventh degrees), which makes sense for someone who wrote the code. The modern optimizing compiler should generate the same code for both examples, so there is no need to use this form, and there is the advantage of adding context.

Using godbolt , we can make sure that this is true, at least for several versions of gcc , clang and icc . Using a simple example with side effects to make sure the code is not fully optimized:

 #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 see that they generate the following to see it live :

 cmpl $128, %ebx 

What we have is an integer constant expression defined in the draft standard section C11 6.6 Constant expressions that state:

An integer constant expression117) must have an integer type and have only operands that are integer constants, enumeration constants, symbolic constants, sizeof expressions, the results of which are integer constants, [...]

and

Constant expressions must not contain assignment, increment, decrement, function call, or commas, except when they are contained in a subexpression that is not evaluated. 115)

and we can see that the constant expression is allowed to evaluate during translation:

A constant expression can be evaluated at translation time and not at run time, and accordingly, can be used anywhere where a constant can be.

+14
Aug 31 '14 at 1:05 a.m.
source share

for (i = 0; i <(1 <7); i ++)

and

for (i = 0; i <128; i ++)

gives the same performance, but the developer can take a huge advantage in the case (i = 0; i <(1 <7); i ++) is used in a loop like

 for(int k = 0; k < 8; k++) { for(int i = 0; i < (1 << k); i++) { //your code } } 

Now it is in the inner upper limit of the cycle, i.e. (1 <k) changes with a power of 2 runtimes. But this is applicable if your algorithm requires this logic.

+5
Aug 30 '14 at 12:41
source share

The compiler outputs the same code for both cases. you probably want to use different forms depending on the context.

  • You can use NUM_STEPS or NUM_ELEMENTS_IN_NETWORK_PACKET when this is a constant part or design choice in your algorithm that you want to clarify.
  • Or you can write 128 to clear it 128 , a constant.
  • Or write 1 << 7 if youโ€™re in a competition and the test said something like โ€œrun it 2 ^ 7 times.โ€

Or you can show that you know bit operations!

In my humble opinion, programming is like writing for two people, a compiler and the person who will have to read it. What you mean should be clear to both.

+3
01 Sep '14 at 12:23
source share

It is evaluated by the preprocessor since both operands are constant.

But if you are going to use a number instead of a bit shift, should not be 0x0100?

-3
Sep 03 '14 at 8:26
source share



All Articles