There are many uses for such a thing.
For example, one for a macro has different behavior in different assemblies. For example, if you want debugging messages, you might have something like this:
#ifdef _DEBUG #define DEBUG_LOG(X, ...) however_you_want_to_print_it #else #define DEBUG_LOG(X, ...)
Another option would be to customize your header file based on your system. This is from my mesa-implemented OpenGL header in linux:
#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) # if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) # define GLAPIENTRY # else # define GLAPIENTRY __stdcall # endif #elif defined(__CYGWIN__) && defined(USE_OPENGL32) # define GLAPIENTRY __stdcall #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 # define GLAPIENTRY #endif #ifndef GLAPIENTRY #define GLAPIENTRY #endif
And used in header declarations, for example:
GLAPI void GLAPIENTRY glClearIndex( GLfloat c ); GLAPI void GLAPIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); GLAPI void GLAPIENTRY glClear( GLbitfield mask ); ...
(I removed the part for GLAPI )
Thus, you get an image, a macro that is used in some cases and not used in other cases, can be defined by something in these cases and nothing for other cases.
Other cases may include:
If the macro does not accept parameters, it may just be a declaration of some case. A well-known example is the protection of header files. Another example might be something like this.
#define USING_SOME_LIB
and then can be used as follows:
#ifdef USING_SOME_LIB ... #else ... #endif
Maybe the macro was used at a certain stage to do something (for example, a log), but then at release the owner decided that the log was no longer useful, and simply deleted the contents of the macro so that it became empty. This is not recommended, but use the method that I mentioned at the very beginning of the answer.
Finally, it can only be for a more detailed explanation, for example, you can say
#define DONT_CALL_IF_LIB_NOT_INITIALIZED
and you write functions like:
void init(void); void do_something(int x) DONT_CALL_IF_LIB_NOT_INITIALIZED;
Although this last case is a little absurd, but it makes sense in this case:
#define IN #define OUT void function(IN char *a, OUT char *b);