如何利用GCC将C语言整数列表宏转换为字符串?
解决C语言宏字符串化逗号分隔列表的编译错误
错误原因
你遇到的编译错误是因为MY_NUMBERS展开后是8个用逗号分隔的常量,而原定义的STR_HELPER(x)只接受1个参数。宏预处理时,逗号会被当作参数分隔符,导致STR_HELPER被传入8个参数,超出其定义的参数数量,从而触发报错。
解决方案:使用可变参数宏
利用C99及以后标准支持的可变参数宏,可以完美处理任意数量的逗号分隔参数,无需额外括号:
// 可变参数版本的字符串化辅助宏 #define STR_HELPER(...) #__VA_ARGS__ // 对外暴露的字符串化宏 #define STR(...) STR_HELPER(__VA_ARGS__) #define MY_NUMBERS 0xA5,0x5A,0x93,0x39,0xF0,0xF0,0x00,0xFF #define MYSTRING "this is my list: " STR(MY_NUMBERS) #include <stdio.h> int main() { printf(MYSTRING); return 0; }
代码说明
__VA_ARGS__是可变参数宏的特殊标识符,会接收所有传入的逗号分隔参数;#__VA_ARGS__会把所有接收的参数整体转换成字符串,不会将逗号解析为参数分隔符;- 这样
STR(MY_NUMBERS)会直接展开为"0xA5,0x5A,0x93,0x39,0xF0,0xF0,0x00,0xFF",和前面的字符串拼接后就能正常输出。
针对旧C标准的兼容方案
如果需要兼容不支持可变参数宏的旧标准,可以将MY_NUMBERS用括号包裹,再通过字符串处理去掉首尾的括号:
#define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) // 手动去除字符串首尾的括号 #define REMOVE_PARENS(str) (str[0] == '(' && str[sizeof(str)-2] == ')') ? (str + 1) : str #define MY_NUMBERS (0xA5,0x5A,0x93,0x39,0xF0,0xF0,0x00,0xFF) #define MYSTRING "this is my list: " REMOVE_PARENS(STR(MY_NUMBERS)) #include <stdio.h> int main() { printf(MYSTRING); return 0; }
这种方法通过STR(MY_NUMBERS)得到带括号的字符串"(0xA5,0x5A,...)",再用REMOVE_PARENS指针偏移去掉首字符(,同时利用字符串末尾的\0自动截断尾括号(因为sizeof(str)包含了\0,所以str[sizeof(str)-2]是最后一个有效字符)。
内容的提问来源于stack exchange,提问作者Antonio Luna
相关产品推荐
相关产品推荐

