2

I have a structure that might have 2 more members depending on a preprocessor variable.

struct foo {
    int m1;
    // ... (other members)
    #ifdef MORE_MEMBERS
    int m2;
    int m3;
    #endif
}

In some parts of the code, I need to change some function calls from func(foo.m1) to func(foo.m1, foo.m2, foo.m3). The last two arguments will be ignored if MORE_MEMBERS is not defined, but I still will get compilation errors from the function calls.

I can think of two solutions:

(1) Use a union. m2 and m3 will just be aliases to m1.

struct foo {
    #ifdef MORE_MEMBERS
    int m1, m2, m3;
    #else
    union {
        int m1, m2, m3;
    }
    #endif
    // ... (other members)
}

(2) Use a wrapper function, while keeping the structure definition without a union.

func2(foo) {
    #ifdef MORE_MEMBERS
        func(foo.m1, foo.m2, foo.m3);
    #else
        func(foo.m1);
    #endif
}

What would be better in the file with the changed function calls? A change of func(int) to func(int,int,int) or func(int) to func2(foo).

3

First suggestion don't do it! Conditional compilations are a great source of hard to find bugs & mysterious crashes. One such example is when part of your code has been compiled with the define in place and another without.

It is almost always better to embed the type within the data so your structure should be:

  • be defined as a type with typedef, a good rule of thumb is to always make structures named types then the compiler can type check for you.
  • contain an enumerate for the variant, member enums rather than magic numbers or #defines and again make those named types so you can see when they are misused
  • then contain a union of the single and multi variable variants.

You can then pass a typed single parameter to your function which will process it differently according to the Variant. Then your compiler will tell you if the function is ever called with something different.

From a quality point of view conditional compilation is bad news and should be reserved for things like platform & compiler specific variations only. From a testing point of view unless you build your code with every combination of switches and test with each you cannot say you have 100% code coverage even when your tools say that you have.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.