jww
jww

Reputation: 102246

Is there a practical reason for "#if defined(X) && (X != 0)"?

I'm working through some cross platform prerpocessor macros. For Microsoft, I read the following should be used:

#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
#   SOME_SETTING_FOR_MY_PROJECT
#endif

The point above is an explicit test for WINAPI_FAMILY was made before the value was used. (I'm pretty sure an undefined macro evaluates to 0).

For Apple, some of the samples on their website use:

#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
#   SOME_SETTING_FOR_MY_PROJECT
#endif

The point above is Apple's sample did not use #if defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0).

Is one more portable than the other?

Is there a practical reason to use one versus the other? Or is this a matter of style?

Note: I'm not really interested in the style of defining some to 0 versus leaving it undefined. If it has practical implications, then I would be interested in insight, though.

Upvotes: 1

Views: 240

Answers (1)

Timo D
Timo D

Reputation: 1803

Even though it is true that an undefined macro default to zero (see gcc), there is a difference between an undefined macro and a macro that has been purposefully set to zero.

Of course, this does not make too much sense for macros like WINAPI_FAMILY because the only valid values for this are 1 and 2. But some macros might have a legitimate meaning behind the value 0 and the meaning might be different to the macro being undefined.

For example, consider a macro for logging levels (LOG_LEVEL) that can be assigned to a certain level (LOG_xxx macros). And if it is not defined by the user it should default to LOG_ERROR (which is 2 and not 0).

#define LOG_NONE     0
#define LOG_WARNING  1
#define LOG_ERROR    2
#define LOG_FATAL    3

Now, if you only check for the value of LOG_LEVEL and it has not been defined by the user or compiler, it will default to LOG_NONE instead of LOG_ERROR. So in that case you will need the defined check as well.

But beyond this, I think that it is more of code style in most cases. I cannot find any C compilers that do not default macro values to zero, so the predominant reason to use defined in your case is to stress that this is not just a value check but also considers that the macro might not have been set at all.

tldr; Being undefined and being set to zero are not the same thing; but in most cases the use of defined is a matter of style or semantic emphasis.

Upvotes: 1

Related Questions