2

拿这个示例代码:

#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.cstrncmp则成为宏,并且在预处理阶段 STRcommaLen 不会扩展。事实上,导致 "code"strncmp的参数被完全剥离。

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

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

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

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

谢谢,艾伦

4

1 回答 1

1

您正确地指出

在预处理阶段 STRcommaLen 未展开

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

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

你的结论

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

也是正确的-这是由__OPTIMIZE__显然由 . 设置的宏控制的-O1

如果我会做这样的事情(我可能不会,就你使用sizeofa展示的陷阱而言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);
}
于 2014-07-04T06:33:25.233 回答