1

I have this line of code:

#define ALPHABET_SIZE 'z' - 'a' + 1

When I hover over ALPHABET_SIZE anywhere in my code it tells me that it expands to 'z' - 'a' + 1. So I wondered if this expression has to be recomputed each time I use ALPHABET_SIZE in my code? If so, how can I prevent the recomputation?

Algo
  • 178
  • 7
  • Feasible, just curious. – Algo Aug 29 '20 at 15:41
  • 1
    I'd expect that would be computed by the compiler at compile time and your code would just have 26s in it, unless you're deliberately compiling with optimization off. – Rup Aug 29 '20 at 15:42
  • Oh, so you are saying that optimization takes care of it automatically? – Algo Aug 29 '20 at 15:44
  • 5
    But beware of `'z'-'a' +1`. Use `('z'-'a'+1)`, otherwise, something like `4*ALPHABET_SIZE` will give you surprising results – JCWasmx86 Aug 29 '20 at 15:50

3 Answers3

5
#define ALPHABET_SIZE 'z' - 'a' + 1

The pre-processor replaces each ALPHABET_SIZE

With

'z' - 'a' + 1

The compiler then will most probably perform Constant folding optimization replacing the computation with 26.


Demo https://godbolt.org/z/Mo46db, the expression is replaced by 26 with gcc 10.2

Tony Tannous
  • 14,154
  • 10
  • 50
  • 86
4

The C standard only specifies the observable behavior of the programs, not how they work under the hood.

Whether or not 'z' - 'a' + 1 is recomputed every time doesn't affect the observable behavior, so it's up to the implementation to decide.

In general, you can expect sensible compilers to compute the result at compile-time, especially when optimizations are enabled.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
2

Consider the following program:

#define ALPHABET_SIZE 'z' - 'a' + 1

#include <stdio.h>


int main(void)
{
    printf("%d\n", 2*ALPHABET_SIZE);
    printf("%d\n", ALPHABET_SIZE*2);
}

In my C implementation, this prints “148” and “27”. This occurs because, in the first printf, 2*ALPHABET_SIZE is replaced with 2*'z' - 'a' + 1, which is evaluated as (2*'z') - 'a' + 1, and, in the second printf, ALPHABET_SIZE*2 is replaced with 'z' - 'a' + 1*2, which is evaluated as 'z' - 'a' + (1*2). Since those produce two different results, it proves that preprocessing with C semantics does not replace a macro with a single expression result computed once; it must produce something else (actually a sequence of preprocessor tokens) that is subsequently reinterpreted in context.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312