这种东西有很多用途。
例如,一个是宏在不同的构建中具有不同的行为。例如,如果你想要调试消息,你可以有这样的东西:
#ifdef _DEBUG
#define DEBUG_LOG(X, ...) however_you_want_to_print_it
#else
#define DEBUG_LOG(X, ...) // nothing
#endif
另一个用途是根据您的系统自定义头文件。这是来自我在 linux 中的台面实现的 OpenGL 标头:
#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__))
# if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) /* The generated DLLs by MingW with STDCALL are not compatible with the ones done by Microsoft's compilers */
# define GLAPIENTRY
# else
# define GLAPIENTRY __stdcall
# endif
#elif defined(__CYGWIN__) && defined(USE_OPENGL32) /* use native windows opengl32 */
# define GLAPIENTRY __stdcall
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
# define GLAPIENTRY
#endif /* WIN32 && !CYGWIN */
#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif
并用于标头声明中,例如:
GLAPI void GLAPIENTRY glClearIndex( GLfloat c );
GLAPI void GLAPIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha );
GLAPI void GLAPIENTRY glClear( GLbitfield mask );
...
(我删除了GLAPI的部分)
所以你得到了图片,在某些情况下使用但在其他情况下不使用的宏可以定义为这些情况下的某些内容,而其他情况下则不定义任何内容。
其他情况如下:
如果宏不带参数,则可能只是为了声明某种情况。一个著名的例子是保护头文件。另一个例子是这样的
#define USING_SOME_LIB
以后可以这样使用:
#ifdef USING_SOME_LIB
...
#else
...
#endif
可能是宏在某个阶段被用来做某事(例如日志),但在发布时,所有者决定日志不再有用,并简单地删除了宏的内容,使其变为空。不过不建议这样做,使用我在答案开头提到的方法。
最后,它可能只是为了更多的解释,例如你可以说
#define DONT_CALL_IF_LIB_NOT_INITIALIZED
然后你编写如下函数:
void init(void);
void do_something(int x) DONT_CALL_IF_LIB_NOT_INITIALIZED;
虽然这最后一种情况有点荒谬,但在这种情况下还是有道理的:
#define IN
#define OUT
void function(IN char *a, OUT char *b);