Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say we have a codebase that is used for many different costumer, and we have some code in it that relevant only for costumers of type X. Is it better to use preprocessor directives to include this code only in costumer of type X, or to use if statement, to be more clear:

// some code
#if TYPE_X_COSTUMER  = 1
// do some things
#endif
// rest of the code

or

if(TYPE_X_COSTUMER) {
    // do some things
}

The arguments I can think about are:

  • Preprocessor directive results in smaller code footprint and less branches (on non-optimizing compilers)
  • If statements results with code that always compiles, e.g. if someone will make a mistake that will harm the irrelevant code for the project he works on, the error will still appear, and he will not corrupt the code base. Otherwise he will not be aware of the corruption.
  • I was always been told to prefer the usage of the processor over the usage of the preprocessor (If this is an argument at all...)

What is preferable - when talking about a code base for many different costumers?

share|improve this question
2  
What are the odds you'll ship a build not created using an optimizing compiler? And if it happens, will the impact matter (especially when put in context with all the other optimizations you'll miss then)? –  delnan Nov 24 '11 at 17:16
    
@delnan - The code is used for many different platforms with many different compilers. And regarding the impact - it might in certain cases. –  MByD Nov 24 '11 at 17:18
    
You were told to prefer something? That is like forcing someone to eat food from the KFC while he does not like chicken. –  rightfold Nov 24 '11 at 21:31
    
@WTP - no I wasn't, I'm interested to know more, so I would make better decisions in the future. –  MByD Nov 24 '11 at 23:12
    
In your second example, is TYPE_X_CUSTOMER still a preprocessor macro? –  detly Nov 25 '11 at 1:15
show 1 more comment

4 Answers

up vote 2 down vote accepted

I think there is one advantage of using a #define that you didn't mention, and that is the fact that you can set the value on the command line (thus, set it from your one-step build script).

Other than that, it is generally better to avoid macros. They don't respect any scoping and that can cause problems. Only very dumb compilers can't optimize a condition based on a compile-time constant. I don't know if that is a concern for your product (for example it might be important to keep the code small on embedded platforms).

share|improve this answer
    
Actually, this is for embedded systems –  MByD Nov 24 '11 at 17:29
    
The problem is that embedded systems are usually using some ancient compiler (like for example gcc 2.95). –  BЈовић Nov 24 '11 at 19:58
    
@VJo - GCC is the lucky case :) –  MByD Nov 24 '11 at 23:13
    
Try it out then. If it includes the unused code and that's a considerable size, then go for the defines. –  Tamás Szelei Nov 24 '11 at 23:58
add comment

As for many questions, the answer of this question is it depends. Instead of saying which is better i have rather given examples and goals where a one is better than other.

Both preprocessor and constant have their own places of appropriate usage.

In case of pre-processor, the code is removed before the compile time. Hence, it is best suited for situations where code is expected not be compiled. This can affect the module structure, dependencies, and it may allow selecting best code segments for performance aspects. In following cases, one must divide code by use of preprocessor only.

  1. Multi-platform code:
    For example, when code is compiled under different platforms, when code has dependency on specific version numbers of OS (or even the compiler version - though this is very rare). For example when you are dealing with little-endien big-endien counterparts of code - they must be segregated with preprocessors rather than constants. Or if you are compiling code for Windows as well Linux and certain system calls are very different.

  2. Experimental Patches:
    Another case where this makes is to have a justified is some experimental code which is risky or certain major modules that needs to be omitted which will have significant linking or performance difference. The reason why one would want to disable the code via preprocessor rather than hiding under if() is because we might not be sure of bugs introduced by this specific change set and we are running under experimental basis. If it fails, we must do nothing else but disable that code in production than rewrite. Some time it is ideal to use #if 0 to comment out the entire code.

  3. Dealing with dependencies:
    Another reason where you may want to generate For example, if you don't want to support JPEG images, you can help get rid of compiling that module/stub and eventually library will not (statically or dynamically) link to that module. Sometimes packages run ./configure to identify availability of such dependency and if libraries are not present, (or user doesn't want to enable) such functionality is disabled automatically without linking with that library. Here it is always beneficial if these directives are auto generated.

  4. Licensing:
    One very interesting of example of preprocessor directive is ffmpeg. It has codecs which can potentially infringe patents by its use. If you download the source and compile to install, it asks you if you want or keep away such stuff. Keeping codes hidden under some if conditions still can land you in court!

  5. Code copy-paste:
    A.k.a macros. This is not an advice to over use macros - just that macros have much more powerful way to apply copy-past equivalent. But use it with great care; and use it if you know what you are doing. Constants of course, cannot do this. But one can use inline functions as well if that is easy to do.

So when do you use constants?
Almost everywhere else.

  1. Neater code flow:
    In general, when you use constants, it is almost indistinguishable from regular variables and hence, it is better readable code. If you write routine that is 75 lines- have 3 or 4 lines after every 10 lines with #ifdef is VERY unable to read. Probably given a primary constant governed by #ifdef, and use it in a natural flow every where.

  2. Well indented code: All preprocessor directive, never work well with otherwise well indented code. Even if your compiler does allow indentation of #def, Pre-ANSI C preprocessor did not allow for space between the start of a line and the "#" character; the leading "#" had to always be placed in the first column.

  3. Configuration:
    Another reason why constants/ or variables make sense is that they can easily evolve from being either linked to globals or in future can be extended to be derived from configuration files.

One last thing:
Never USE preprocessor directives #ifdef to #endif crossing the scope or { ... }. i.e. start of #ifdef or end of #endif on different sides of { ... }. This is extremely bad; it can be confusing, it can be sometime dangerous.

This of course, is not an exhaustive list, but shows you stark difference, where which method is more apt to use. It is not really about which is better, it is alway more of which one is more natural to use in given context.

share|improve this answer
    
Thanks for the long and detailed answer. I was aware to most of the things you mentioned and they were omitted from the question since the question is not whether to use preprocessor capabilities at all, but about a specific type of usage. But I think the basic point you made is true. –  MByD Nov 25 '11 at 0:29
    
"Never USE preprocessor directives #ifdef to #endif crossing the scope or { ... }" it depends on IDE. If IDE recognizes inactive preprocessor blocks and collapses them or shows with different color, it's not confusing. –  Abyx Dec 1 '11 at 13:06
    
@Abyx it is true that IDE may help. However, in many cases where people develop under *nix (linux etc.) platform - the choice of editors etc. are many (VI, emacs and so on). So someone else may be using a different editor than yours. –  Dipan Mehta Dec 2 '11 at 6:35
add comment

Do your customers have access to your code? If yes, then preprocessor could be a better option. We have something similar and we use compile time flags for various customer (or customer specific features). Then a script could extract customer specific code and we ship that code. The customers are not aware of other customers or other customer specific features.

share|improve this answer
add comment

Long story short: the fears about preprocessor directives are basically 2, multiple inclusions and maybe less readable code and a more criptic logic.

If your project is small with almost no big plan for the future, i think that both options offers the same ratio between pros and cons, but if your project is going to be huge, consider something else like the writing of a separate header file if you still want to use preprocessor directives, but keep in mind that this kind of approach usually makes the code less readable and be sure that the name of that constants means something for the business logic of the program itself.

share|improve this answer
    
This is a great code base, and the defines are in some separate headers indeed. –  MByD Nov 24 '11 at 17:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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