gcc优化:如何处理strncmp中的宏扩展&;其他职能

gcc优化:如何处理strncmp中的宏扩展&;其他职能,gcc,macros,compiler-optimization,c-preprocessor,Gcc,Macros,Compiler Optimization,C Preprocessor,以以下示例代码为例: #include <string.h> #define STRcommaLEN(str) (str), (sizeof(str)-1) int main() { const char * b = "string2"; const char * c = "string3"; strncmp(b, STRcommaLEN(c)); } #包括 #定义STRcommaLEN(str)(str),(str)-1的大小 int main(){

以以下示例代码为例:

#include <string.h>
#define STRcommaLEN(str) (str), (sizeof(str)-1)

int main() {
    const char * b = "string2";
    const char * c = "string3";
    strncmp(b, STRcommaLEN(c));
}
#包括
#定义STRcommaLEN(str)(str),(str)-1的大小
int main(){
const char*b=“string2”;
const char*c=“string3”;
strncmp(b,STRcommaLEN(c));
}
如果您不在GCC中使用优化,一切都可以,但是如果您添加-O1和更高版本,如
GCC-E-std=gnu99-Wall-Wextra-c-I/usr/local/include-O1 sample.c
,则
strncmp
将成为一个宏,并且在预处理阶段STRcommaLen不会展开。事实上,结果“code”
strncmp
的参数被完全剥离

我知道如果我添加
#定义NEWstrncmp(a,b)strncmp(a,b)
并使用它,问题就会消失。然而,将您自己的函数映射到每个可能成为宏的标准函数似乎不是一个很好的解决方案

我试图找到具体的优化是它的责任,但失败了。事实上,如果我用它根据
mangcc
启用的所有标志替换-O1,问题就会消失。我的结论是-O1添加了一些不受标志控制的优化,这就是其中之一

您将如何以通用方式处理此问题?可能有一些我不熟悉的宏魔术,或者我没有看过的编译器标志?我们有许多宏和大量的代码库-这段代码只是为了演示一个示例而编写的

顺便说一句,GCC版本/平台是
GCC版本4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5)

谢谢,
阿伦

你正确地指出

在预处理阶段,STRcommaLen不展开

-更准确地说,不是在扩展
strncmp
宏之前。这不可避免地会导致您可能忽略或忘记提及的错误:

sample.c:7:30: error: macro "strncmp" requires 3 arguments, but only 2 given
你的结论

即-O1添加了一些不受标志和参数控制的优化 这是其中之一

也是正确的-这是由宏
\uuuu OPTIMIZE\uuu
控制的,该宏显然由
-O1
设置

如果我会做这样的事情(考虑到您使用
sizeof
a
char*
演示的陷阱,我可能不会这么做),我仍然会选择

将您自己的函数映射到可能成为 宏

-但更像

#include <string.h>
#define STRNCMP(s1, s2) strncmp(s1, s2, sizeof(s2)-1)

int main()
{
    const char b[] = "string2";
    const char c[] = "string3";
    STRNCMP(b, c);
}
#包括
#定义STRNCMP(s1,s2)STRNCMP(s1,s2,sizeof(s2)-1)
int main()
{
常量字符b[]=“string2”;
常量字符c[]=“string3”;
STRNCMP(b,c);
}

如果优化破坏了一个有效的程序,那就是应该报告的编译器错误。与gcc无关,是glibc选择将strncmp设置为宏。glibc这样做是完全合法的,请参见C99 7.1.4,第一段。“头中声明的任何函数都可以作为类似宏的函数”Try
(strncmp)(b,STRcommaLEN(c))
。谢谢你的评论,@Bamar-我正要把它报告为一个bug,但我发现它不是bug,他们也不会做任何事情。