Search code examples
cdefinition

Sanity check on definitions from arrays


I'm hunting for the cause of a bug and think I may have found it if my understanding of using #define is correct.

As i understand it, once you define something, its set that way, even if the define is filled with the value of a variable, it sticks with the value at the time of compile and would not change if the variable changed later? So this code:

int values[] = {5,6,7,8};
int x = 0;
#define DEF_VALUE values[x]

DEF_VALUE would be 5, as 5 is the value of position 0 in the values array.

But if I was to do this:

int values[] = {5,6,7,8};
int x = 0;
#define DEF_VALUE values[x]
x = 2;

DEF_VALUE would still be 5 as that was the output of values[x] at the time that #define was called, so changing the value of x later to 2 would not cause a change in DEF_VALUE to 7 (the value of position 2 in the values array).

Is my logic here correct?

If so I think I've found my bug as the original programmer of this code was relying on updating x to update the value of DEF_VALUE later in the code for a location address for selections.


Solution

  • The way #define works in C is that it creates an expansion, that is any place where DEF_VALUE occurs, the compiler treats it as if values[x] was written. The C pre-processor effectively re-writes the code by applying these expansions and the resulting re-written code is what's supplied to the compiler.

    In this case changing x has the effect of changing what DEF_VALUE ultimately evaluates to, but not what it expands to.

    In your second case it expands to 7 if and only if x is 2. If this #define is used in another scope then the results are unknown or a syntax error depending on what variables are present.

    Some test code:

    void demo() {
      int values[] = {5,6,7,8};
      int x = 0;
      #define DEF_VALUE values[x]
      x = 2;
    
      printf("%d\n", DEF_VALUE);
    }
    

    Here it shows 7 as expected.

    Once the pre-processor has finished with this code it ends up in this form:

    void demo() {
      int values[] = {5,6,7,8};
      int x = 0;
      x = 2;
    
      printf("%d\n", values[x]);
    }
    

    If later in your code you have this:

    void other() {
      printf("%d\n", DEF_VALUE);
    }
    

    You get a syntax error. That's because the code the compiler is told to work with is actually:

    void other() {
      printf("%d\n", values[x]);
    }
    

    As neither values nor x are present in that scope it can't compile.