Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What use cases necessitate #define without a token-string?

I have encountered the #define pre-processor directive before while learning C, and then also encountered it in some code I read. But apart from using it to definite substitutions for constants and to define macros, I've not really understook the special case where it is used without a "body" or token-string.

Take for example this line:

#define OCSTR(X)

Just like that! What could be the use of this or better, when is this use of #define necessary?

like image 282
JWL Avatar asked Sep 29 '11 08:09

JWL


3 Answers

This is used in two cases. The first and most frequent involves conditional compilation:

#ifndef XYZ
#define XYZ
//  ...
#endif

You've surely used this yourself for include guards, but it can also be used for things like system dependencies:

#ifdef WIN32
//  Windows specific code here...
#endif

(In this case, WIN32 is more likely defined on the command line, but it could also be defined in a "config.hpp" file.) This would normally only involve object-like macros (without an argument list or parentheses).

The second would be a result of conditional compilation. Something like:

#ifdef DEBUG
#define TEST(X) text(X)
#else
#define TEST(X)
#endif

That allows writing things like:

TEST(X);

which will call the function if DEBUG is defined, and do nothing if it isn't.

like image 184
James Kanze Avatar answered Sep 28 '22 17:09

James Kanze


Such macro usually appears in pair and inside conditional #ifdef as:

#ifdef _DEBUG
   #define OCSTR(X)
#else
   #define OCSTR(X)  SOME_TOKENS_HERE
#endif

Another example,

#ifdef __cplusplus
   #define NAMESPACE_BEGIN(X) namespace X {
   #define NAMESPACE_END }
#else
   #define NAMESPACE_BEGIN(X) 
   #define NAMESPACE_END
#endif
like image 21
Nawaz Avatar answered Sep 28 '22 18:09

Nawaz


One odd case that I recently dug up to answer a question turned out to be simply commentary in nature. The code in question looked like:

void CLASS functionName(){
  //
  //
  //
}

I discovered it was just an empty #define, which the author had chosen to document that the function accessed global variables in the project:

C++ syntax: void CLASS functionName()?

So not really that different from if it said /* CLASS */, except not allowing typos like /* CLAAS */...some other small benefits perhaps (?)

like image 34
HostileFork says dont trust SE Avatar answered Sep 28 '22 18:09

HostileFork says dont trust SE