Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why an expression instead of a constant, in a C for-loop's conditional?

In many programming competitions I have seen people write this type of for-loop

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

Unless I am missing something, that's the same as

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

Why use the (1 << 7) version?
Isn't calculating the condition every time an unnecessary overhead?

like image 554
harrythomas Avatar asked Aug 30 '14 11:08

harrythomas


People also ask

What is a constant expression in C?

A constant expression gets evaluated at compile time, not run time, and can be used in any place that a constant can be used. The constant expression must evaluate to a constant that is in the range of representable values for that type.

What is the purpose of three expressions in for loop?

If the condition is true, the "body" of the loop is executed. If not, control passes to the statement (if any) directly after the body of the loop. After the body is executed, the "change" is done. This can be increment, decrement of the initialized variable(s) or something else.

What is the purpose of the condition in a for loop?

Condition is an expression that is tested each time the loop repeats. As long as condition is true, the loop keeps running. Increment is an expression that determines how the loop control variable is incremented each time the loop repeats successfully (that is, each time condition is evaluated to be true).

Does a while loop require a condition?

A "While" Loop is used to repeat a specific block of code an unknown number of times, until a condition is met. For example, if we want to ask a user for a number between 1 and 10, we don't know how many times the user may enter a larger number, so we keep asking "while the number is not between 1 and 10".


4 Answers

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

like image 190
ouah Avatar answered Oct 18 '22 23:10

ouah


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.

like image 22
barak manos Avatar answered Oct 18 '22 22:10

barak manos


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.

like image 19
Yu Hao Avatar answered Oct 18 '22 23:10

Yu Hao


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.

like image 14
Shafik Yaghmour Avatar answered Oct 18 '22 22:10

Shafik Yaghmour