如何使用算术生成预处理器定义?

时间:2019-04-23 23:59:37

标签: c++ c macros c-preprocessor string-literals

我想动态创建处理器前文字字符串,其中部分字符串是通过某种算术创建的,例如:math(x) x - 0x1234。生成的定义将由宏:get_tex_uniform_name(unit)进行,结果将与以下数字顺序定义的值相同:

// texture uniform naming
#define TEX_UNIFORM_BASE_NAME       "tex"
#define TEX_UNIFORM_0               TEX_UNIFORM_BASE_NAME"0"  // "tex0" and so on
#define TEX_UNIFORM_1               TEX_UNIFORM_BASE_NAME"1"
#define TEX_UNIFORM_2               TEX_UNIFORM_BASE_NAME"2"
#define TEX_UNIFORM_3               TEX_UNIFORM_BASE_NAME"3"

我尝试使用STRINGIFY(#)从头开始生成字符串:

#define get_tex_unit_num(unit) unit - GL_TEXTURE0
// create string literal from whatever is put in
#define STRINGIFY(x) #x
#define LITERAL_STRINGIFY(x) STRINGIFY(x)
#define get_tex_uniform_name(unit) TEX_UNIFORM_BASE_NAME LITERAL_STRINGIFY(get_tex_unit_num(unit))

// issue: result is "texunit - 0x84C0", 0x84C0 being GL_TEXTURE0

我尝试使用令牌粘贴来与现有定义一起使用:

#define get_tex_unit_num(unit) unit - GL_TEXTURE0
#define get_tex_uniform_name(unit) TEX_UNIFORM_ ## get_tex_unit_num(unit)

// error: TEX_UNIFORM_get_tex_unit_num is undefined

并且一直在尝试使某种位掩码起作用:

#define TEX_UNIFORM_BASE_NAME       "tex "

#define get_tex_unit_num(unit) unit - GL_TEXTURE0
#define get_tex_uniform_name(unit) TEX_UNIFORM_BASE_NAME & (0xffffff00 + (char)get_tex_unit_num(unit))

// error: expression must have integral or unscoped enum type

我知道这可以通过函数来​​完成,也可以仅使用第一个示例中定义的串联文字字符串来完成。我并不一定要寻找我的示例不起作用的原因。我正在寻找一种动态获取这些字符串的方法,并且在使用宏内部算术创建字符串文字时遇到麻烦。

2 个答案:

答案 0 :(得分:2)

您的第一个代码示例应该可以工作,因此没有必要将字符串文字粘贴到预处理器中。这也是不可能的。

这是不可能的,因为##将两个预处理令牌粘贴在一起,并且结果必须是有效的预处理令牌。预处理令牌是标头名称,标识符,预处理编号,字符常量,字符串文字,标点符号或单个非空白字符。您不能将两个字符串文字粘贴在一起,也不能删除它们之间的两个引号。但是,通常没有必要将它们粘贴在一起。只需让它们彼此相邻扩展就足够了,因为相邻的字符串文字是串联在一起的。

您的第一个代码示例可以生成类似"tex" "0"的结果。经过预处理之后,再进行分析和转换(编译)之前,相邻的字符串文字将转换为单个串联的字符串文字。因此不会有任何优先权或其他语法和语义上的问题。

答案 1 :(得分:0)

我想通过参考已经回答了这个问题的问题来为以后的观众总结这个问题: Can the C preprocessor perform integer arithmetic?

简而言之,如果在评估恒定条件时使用预处理器,则可以进行算术运算:

#if 1 + 2 == 5
#endif
#else
#endif

但是,由于您无法将宏与此结合使用,因此您无法在编译之前进行make字符串文字定义。