gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > C++ council, should we #ifdef?

#140634 - keldon - Tue Sep 18, 2007 4:43 pm

Code:
// somewhere
#define OPTION_X 1

// somewhere else
#ifdef OPTION_X
   /* some code */
#endif

vs
Code:
// somewhere
const BOOL OPTION_X = TRUE;

// somewhere else
   if ( OPTION_X )
   {
      /* some code */
   }


What are your thoughts on it?

#140638 - kusma - Tue Sep 18, 2007 5:23 pm

It's not necessarily the same, 'const' doesn't guarantee that a variable isn't changed in C. To quote K&R (section 2.4, page 40);
Quote:
The result is implementation-defined if an attempt is made to change a const.

Some compilers might support it, others might not. Of course, it's bad coding practice to change it.

#140639 - sajiimori - Tue Sep 18, 2007 5:42 pm

Although they are not "the same" as #defines (thankfully), static const values are sometimes truly immutable. In particular, const integer primitives initialized with compile-time constants are also compile-time constants, and can therefore be used as array sizes and switch cases, among other things.
Code:
static const int kSize = 5;

// Okay in C++, but not in C.
int array[kSize];

Any beginner's C++ book will give some reasons to avoid the preprocessor, of which correct scoping is the most important.


Last edited by sajiimori on Tue Sep 18, 2007 5:43 pm; edited 1 time in total

#140640 - gmiller - Tue Sep 18, 2007 5:42 pm

It might not matter for you but with an #ifdef the code is never emitted by the compiler so your object file could be smaller. Depending on the compiler and the number of source files involved the const declaration could do the same thing for you. The #ifdef is guaranteed to either generate code or not the const code is dependent on the compiler.

If you absolutely need the space that the code would take up us #ifdef otherwise take your chances.

#140641 - sajiimori - Tue Sep 18, 2007 5:47 pm

Don't "take your chances" -- read the compiler's output. If you're working on a legacy platform with crappy C++ support, it's better to know so you can stick to older language features.

That said, modern versions of GCC behave reasonably with regards to static const variables.

#140642 - sajiimori - Tue Sep 18, 2007 5:54 pm

Oops, I didn't read the original post closely enough. Indeed, #ifdef is a whole other beast. There are often ways to avoid it using templates, but they tend to be overly complicated for my taste.

My best suggestion is to condense your #ifdeffery to small areas (preferably configuration files), and keep them away from business logic.

#140848 - Mumbly Juergens - Thu Sep 20, 2007 6:20 am

According to something I read that I can't remember the name of, good compilers will (depending on the optimization flags) remove a section of code that will never be run, as shown in the example in the original post.

I vote for using constants if your compiler cuts out the code, simply because then you will get warnings and errors for the code in the if block even if it gets cut out later. With an ifdef you could find yourself with code that doesn't work and not find out until you change a define.

On the other hand, most coders know that an ifdef block is intentionally there to remove unwanted code based on a define, where using an if might confuse some people as it fits right in with other code (also making it harder to spot if you ever start removing them).

#140878 - tepples - Thu Sep 20, 2007 11:24 am

Mumbly Juergens wrote:
According to something I read that I can't remember the name of, good compilers will (depending on the optimization flags) remove a section of code that will never be run, as shown in the example in the original post.

But don't rely on this entirely. I've seen some situations where the G++ toolchain leaves unreachable code behind in the binary. If you want to make sure code is completely removed, use -save-temps and read the input to the assembler.

Quote:
I vote for using constants if your compiler cuts out the code, simply because then you will get warnings and errors for the code in the if block even if it gets cut out later.

With a large number of these being "warning: unused variable xyz", right?

Quote:
With an ifdef you could find yourself with code that doesn't work and not find out until you change a define.

But if you change a macro (such as #define HAS_FPU in one project I work on, which among other things switches between sprintf and siprintf), you'll find out when you build the version for another platform that sets the macro the other way and invokes the code that is unused in a given circumstance.

Quote:
On the other hand, most coders know that an ifdef block is intentionally there to remove unwanted code based on a define, where using an if might confuse some people as it fits right in with other code (also making it harder to spot if you ever start removing them).

In either case, comments clarify the intent.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.