获取此示例代码:
#include <string.h>
#define STRcommaLEN(str) (str), (sizeof(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不是扩大。事实上,在结果中“代码”strncmp
的参数被完全剥离。
我知道如果我添加#define NEWstrncmp(a, b) strncmp (a, b)
并使用它,问题就会消失。但是,将您自己的函数映射到可能成为宏的每个标准函数似乎都不是一个很好的解决方案。
我尝试找到负责它的特定优化并失败了。实际上,如果我用根据man gcc
启用的所有标志替换-O1,问题就会消失。我的结论是-O1增加了一些不受标志控制的优化,这是其中之一。
您将如何以通用方式处理此问题?可能有一些我不熟悉的宏魔法或者我没看过的编译器标志?我们有许多宏和一个实质性的代码库 - 这段代码只是为了演示一个例子。
顺便说一下,GCC版本/平台是gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
。
谢谢, 阿伦
答案 0 :(得分:1)
你正确地注意到了
在预处理阶段STRcommaLen未展开
- 更准确地说,不是在strncmp
宏扩展之前。这不可避免地导致您可能忽略或忘记提及的错误:
sample.c:7:30: error: macro "strncmp" requires 3 arguments, but only 2 given
你的结论
-O1添加了一些不受标志和控制的优化 这是其中之一
也是正确的 - 这由宏__OPTIMIZE__
控制,显然由-O1
设置。
如果我做了类似的事情(我可能不会,因为你使用sizeof
和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);
}