使用C宏替换strncmp参数在不同GCC版本编译异常问题排查
宏展开引发strncmp参数报错的版本差异原因
问题情况
用户定义了一个简化字符串长度传递的宏:
#define STRING_WITH_SIZE_MINUS_ONE(x) x, sizeof(x)-1
然后在代码里这么使用:
if (0 == strncmp(str1, STRING_WITH_SIZE_MINUS_ONE("str2")) { // 业务逻辑 }
用arm-linux-gnueabihf-gcc 4.9.2编译时,弹出错误:
error: macro "strncmp" requires 3 arguments, but only 2 given
但换成arm-linux-gnueabihf-gcc 8.3.0编译就完全正常。
报错根源
核心原因是不同GCC版本的标准库对strncmp的实现方式不一样:
- GCC 4.9.2的标准库把
strncmp定义成了普通预处理宏。预处理阶段处理宏时,会先拆分参数列表——此时STRING_WITH_SIZE_MINUS_ONE("str2")会被当成一个完整的参数,所以strncmp拿到的是str1和这个宏表达式两个参数,不符合宏要求的3个参数,直接报错。 - GCC 8.3.0的标准库要么把
strncmp作为普通函数实现,要么调整了宏的定义逻辑(比如用内置函数包装)。这时候预处理会先展开内层的STRING_WITH_SIZE_MINUS_ONE宏,把它变成"str2", sizeof("str2")-1,最终strncmp得到3个合法参数,自然编译通过。
说白了就是旧版本GCC的strncmp宏不认这种“嵌套宏补参数”的写法,新版本的实现逻辑允许这种操作。
内容的提问来源于stack exchange,提问作者phil
相关产品推荐
相关产品推荐

