C/C++ 宏展开顺序

文章目录
  1. 1. 参考资料
  2. 2. 参考

参考资料

今天阅读torch Tensor库的时候看到如下的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef TH_TENSOR_INC
#define TH_TENSOR_INC

#include "THStorage.h"
#include "THTensorApply.h"

#define THTensor TH_CONCAT_3(TH,Real,Tensor)
#define THTensor_(NAME) TH_CONCAT_4(TH,Real,Tensor_,NAME)

/* basics */
#include "generic/THTensor.h" // 为什么是先include THTensor.h??
#include "THGenerateAllTypes.h"

#include "generic/THTensor.h"
#include "THGenerateHalfType.h"
/* more codes */

我最大的疑惑是为什么不是先包含类型定义文件THGenerateAllTypes.h, 在包含模板文件generic/THTensor.h. 查阅才发现, 宏展开的顺序和#define的顺序没有必然关系, 宏预处理器会对代码扫描两次, 对必要的参数完全展开, 再进行外层的展开. gcc编译器做了如下说明:

Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringized or pasted with other tokens. After substitution, the entire macro body, including the substituted arguments, is scanned again for macros to be expanded. The result is that the arguments are scanned twice to expand macro calls in them.

意思是:

  1. 如果宏连接字符串, 参数不展开
  2. 如果宏把参数转换为字符串, 参数不占开
  3. 不满足1,2两个情况的参数会被完全展开

例如:

1
2
3
4
5
6
7
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE

AFTERX(BUFSIZE) // -> X_BUFSIZE
XAFTERX(BUFSIZE) // -> X_1024

参考