13

I think about conditionals and compilers. I am programming an application for Arduino and so I need the application to be as fast as possible.

In my code I have this:

#define DEBUG false    

...

if (DEBUG)
{
  String pinName;
  pinName = "Pin ";
  pinName += pin;
  pinName += " initialized";
  Serial.println(pinName);
}

I am wondering if the compiler does not include the code (code in if block) in binary file. The conditions is always false, so the program never goes there.

And from the other side. What if DEBUG is true? Does Arduino test the condition or the compiler include only the body of if in binary file?

I found this site https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html about #if directive, so I can rewrite the code to have these directives instead of "normal" if. But I would like to know if I should rewrite it or if it would be waste of time.

codingenious
  • 8,385
  • 12
  • 60
  • 90
Martin Pohorský
  • 431
  • 3
  • 15
  • 3
    A smart compiler will do the optimization and will not include the code in binary if `DEBUG` is `false`. – The Philomath Aug 19 '16 at 08:36
  • 7
    `if (CONSTANT) { ... }` is very easy for a compiler to optimize. I would expect that any decent compiler from at least the last 25 years should be able to remove the conditional branch. – Phylogenesis Aug 19 '16 at 08:37
  • 4
    I'd use `#if`/`#endif`, even if it doesn't make a difference in the binary. That way it's clear what `DEBUG` is. – LogicStuff Aug 19 '16 at 08:39
  • 3
    @LogicStuff: It is a bad idea to use #if/#endif because the compiler will not check the code if the condition is false. We know that any real world compiler will optimize the code out as with #if/#endif I tend to use not macro stuff! – Klaus Aug 19 '16 at 08:48
  • _I need the application to be as fast as possible._ -- write it in assembly not in C/C++. – Aleksander Z. Aug 19 '16 at 10:32
  • 1
    @AleksanderZ.Okay, nice comment. But I also need WiFi control and HTTP communication. And I would like to finish it in this life span :). – Martin Pohorský Aug 19 '16 at 10:36

3 Answers3

10

Any half-decent optimizing compiler will remove the whole code inside the if statement, if it can tell at compile-time that the condition always evaluates to false. Similarly, any half-decent compiler would skip the check itself if the condition is always true.

Indeed this is completely equivalent to "compiler switches" such as:

#define DEBUG


#ifdef DEBUG
...
#endif

The "compiler switch" syntax with #ifdef is to prefer, as it makes the intent clearer to other C programmers. But that's just a matter of coding style - it will result in the same binary as your original code.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

The code you wrote should never be executed, however, it could be available in the executable.

I would say that the compiler would be required on keeping this code when you would disable optimizations (like adding -O0 to Clang and GCC). In all other cases, I would hope that the compiler would remove the code as this is a very simple optimization with a remarkable code size effect. For instance, GCC eliminates this at -O and higher. (See the manual)

Though, there are 2 other ways of writing your code, which will enforce this code to not be included:

  • Preprocessor conditionals
  • constexpr if

By making use of the preprocessor conditionals, you will be able to remove the code before it reaches the actual compiler. It might be a bit intrusive for your indenting, though it will work with all compilers and versions from the C and C++ standards.

#ifdef DEBUG
   { // Optional: Adding extra scope to prevent usage of local variables after the endif
   // Code to eliminate
   }
#endif

However, if you are using C++17, you could also use constexpr if. This will be less intrusive in your code and although the code in the if-statement has to be syntactic correct, it doesn't have to compile (so not semantically correct).

This can be written as:

if constexpr (DEBUG)
{
    // Code to eliminate
}
JVApen
  • 11,008
  • 5
  • 31
  • 67
  • is it `if constexpr` ? – RiaD Aug 19 '16 at 11:07
  • No, it is `constexpr if`. I've added a link to the proposal in my reply. – JVApen Aug 19 '16 at 11:40
  • I believe it's outdated http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0292r1.html https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/ – RiaD Aug 19 '16 at 12:22
0

I do not like answering my own question, because I would not figure it out without your help, guys.

Anyway, first option is to use:

#if DEBUG == true
#endif

or

#ifdef DEBUG
#endif

the compiler does not get the code in #if / #ifdef (preprocessor removes it), so if there is a problem in this part of code, no one would know about it if DEBUG is set to false or is not defined at all (thanks @Klaus).

Second option:

#define DEBUG false    

...

if (DEBUG)
{
  ...
}

Any newer compiler should remove the 'if' block if the condition is false or remove the 'if' statement and leave body if the condition is true.

So I would say it is on programmer which approach suites better the needs of application.

The first approach is better if you need to be sure the code would not be included in binary.

The second approach is better if you want the compiler to check the whole code each time you compile the program.

If you like this answer, vote for it and I will accept it - if no one provides a better one.

Martin Pohorský
  • 431
  • 3
  • 15
  • `#if DEBUG == true` can be replaced with `#if DEBUG`. The other option is `#ifdef DEBUG`. For some definitions like library options you can use `#if` style, but specifically for `DEBUG` it is better to use `#ifdef` syntax. – i486 Sep 13 '16 at 11:47