【问题标题】:gcc optimizations: how to deal with macro expantion in strncmp & other functionsgcc 优化:如何处理 strncmp 和其他函数中的宏扩展
【发布时间】:2013-05-10 21:56:47
【问题描述】:

获取此示例代码:

#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 没有展开。事实上,结果“代码”strncmp 的参数被完全剥离。

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

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

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

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

谢谢, 阿伦

【问题讨论】:

  • 如果优化破坏了一个有效的程序,那就是应该报告的编译器错误。
  • 与gcc无关,是glibc选择将strncmp做成宏。
  • glibc 这样做是完全合法的,参见 C99 7.1.4,第一段。 “在头文件中声明的任何函数都可以另外实现为类似函数的宏”
  • 试试(strncmp)(b, STRcommaLEN(c));
  • 感谢 cmets,@Bamar - 当我发现它不是错误并且他们不会对此采取任何措施时,我正准备将其报告为错误。

标签: gcc macros compiler-optimization c-preprocessor


【解决方案1】:

你正确地注意到了

在预处理阶段 STRcommaLen 未展开

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

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

你的结论

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

也是正确的 - 这是由宏 __OPTIMIZE__ 控制的,显然是由 -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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多