无需替换 C++ 的预处理器宏
Preprocessor macro without replacement C++
根据cplusplus.com,定义宏的语法是:
#define identifier replacement
但是,我有时会偶然发现不包含替换的宏定义。例如在afxwin.h中,有如下预处理器定义:
#define afx_msg // intentional placeholder
我的问题:
- 如果使用没有替换的预处理器定义,编译时会发生什么?它只是被忽略了吗?例如,行
afx_msg void OnAddButton();
是否变为 void OnAddButton();
?
- 不替换地使用预处理器的目的是什么?难道只是为了让代码更清晰?
- 预处理器对其进行处理,将其删除并替换为空
- 可能有多种原因,包括可读性、可移植性、自定义编译器功能等
#define bla
简单定义bla
.
您可以将它与
一起使用
#ifdef bla
...
place some code here
...
#endif
一个典型的用例是#define DEBUG
在调试模式下启用特殊代码部分。
从 "outside" 设置此类内容的另一种方法是:
g++ -DDEBUG x.cpp
这也设置了定义的宏DEBUG。
每个头文件都应该有这样的东西:
#ifndef THIS_HEADER_INCLUDE_GUARD
#define THIS_HEADER_INCLUDE_GUARD
...
rest of header file
...
#endif
这只是保护您的头文件(递归地)阅读更多一次。
有些可以通过具体实现来完成 #pragma once
。
"Nothing"(无文本)是宏的有效替换文本。它会被预处理器简单地删除(更准确地说,什么都不替换)。
您使用这样的东西有多种原因。一种是简单地使用 #ifdef
中的宏和类似的构造函数。
还有一个就是条件编译。一个典型的用例是 public API 和 DLL 导出。在 Windows,您需要将函数标记为从 DLL 导出(在构建 DLL 时)或从 DLL 导入(在链接到 DLL 时)。在 ELF 系统上,不需要这样的声明。因此,您会经常在 public 库 headers:
中看到这样的代码
#ifdef _WIN32
#ifdef BUILDING_MYLIB
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
void MYLIB_API myApiFunction();
另一个原因可能是代码处理工具。也许你有一个工具可以解析源代码,提取带有特定标记的函数列表。您可以将这样的标记定义为空宏。
根据cplusplus.com,定义宏的语法是:
#define identifier replacement
但是,我有时会偶然发现不包含替换的宏定义。例如在afxwin.h中,有如下预处理器定义:
#define afx_msg // intentional placeholder
我的问题:
- 如果使用没有替换的预处理器定义,编译时会发生什么?它只是被忽略了吗?例如,行
afx_msg void OnAddButton();
是否变为void OnAddButton();
? - 不替换地使用预处理器的目的是什么?难道只是为了让代码更清晰?
- 预处理器对其进行处理,将其删除并替换为空
- 可能有多种原因,包括可读性、可移植性、自定义编译器功能等
#define bla
简单定义bla
.
您可以将它与
一起使用#ifdef bla
...
place some code here
...
#endif
一个典型的用例是#define DEBUG
在调试模式下启用特殊代码部分。
从 "outside" 设置此类内容的另一种方法是:
g++ -DDEBUG x.cpp
这也设置了定义的宏DEBUG。
每个头文件都应该有这样的东西:
#ifndef THIS_HEADER_INCLUDE_GUARD
#define THIS_HEADER_INCLUDE_GUARD
...
rest of header file
...
#endif
这只是保护您的头文件(递归地)阅读更多一次。
有些可以通过具体实现来完成 #pragma once
。
"Nothing"(无文本)是宏的有效替换文本。它会被预处理器简单地删除(更准确地说,什么都不替换)。
您使用这样的东西有多种原因。一种是简单地使用 #ifdef
中的宏和类似的构造函数。
还有一个就是条件编译。一个典型的用例是 public API 和 DLL 导出。在 Windows,您需要将函数标记为从 DLL 导出(在构建 DLL 时)或从 DLL 导入(在链接到 DLL 时)。在 ELF 系统上,不需要这样的声明。因此,您会经常在 public 库 headers:
中看到这样的代码#ifdef _WIN32
#ifdef BUILDING_MYLIB
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
void MYLIB_API myApiFunction();
另一个原因可能是代码处理工具。也许你有一个工具可以解析源代码,提取带有特定标记的函数列表。您可以将这样的标记定义为空宏。