我有一个文件“test.cxx”

namespace net {
    extern "C" {
#include <arpa/inet.h>
    }
}

int main() {
    htons(1024);
}

使用 -O1 或更多编译时一切正常。

使用 -O0 编译时:
error: ‘htons’ was not declared in this scope
suggested alternative: ‘net::htons’

然后我将 htons 更改为 net::htons

使用 -O0 编译时一切正常。

使用 -O1 或更多编译时:
error: expected unqualified-id before ‘(’ token

在 gcc-4.9.2 和 clang-3.7.0 上转载。
有人可以解释为什么会这样吗?

最佳答案

发生这种情况的原因是,在-O0处,调用被编译为htons函数,而您对该函数的声明在namespace net内部。在优化版本中,例如 -O2,调用被宏替换。

您可以通过使用 gcc -O0 -E v/s gcc -O2 -E 预编译您的程序来验证这一点

使用 htons 时
-O2htons 被转换为

int main() {
    (__extension__ (
       {
          register unsigned short int __v, __x = (unsigned short int) (1024);
          if (__builtin_constant_p (__x))
             __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8)));
          else
             __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc");
          __v;
      }
    ));
}

使代码不抛出解析错误。



当使用 net::htons 时

当您用 ntohs 替换 net::ntohs 时,ntohs 定义被使用/公开以进行优化,并且您的预处理代码如下所示:
int main() {
  net::(__extension__ ({... /* removed for Brevity */ ...}));
}

因此错误



为什么会发生 htons 可以实现为函数或宏。如果它被定义为宏,htons 就可以正常工作。但是如果它被定义为一个函数 net::htons 就可以正常工作。

它出现在-O1或更高版本中,头文件公开了宏版本而不是函数。

可能的解决方案
using namespace net;  // Not recommended
#ifndef htons  // Recommended
using net::htnos;
#endif
extern "C" { // Add all declarations in global space
#include <arpa/inet.h>
}

关于命名空间前缀解析和优化级别依赖中带有 extern "C"的 C++,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28872710/

10-11 06:38