ARM上的`ntohs(...)`错误的`-Wsign-conversion`错误?

时间:2016-01-25 23:31:52

标签: c++ g++ arm cross-platform

这是一个SSCCE,显示了我的代码的简化版本,它仍然有用:

//Compile with -O3 -Wsign-conversion

#include <arpa/inet.h>
#include <string>

void _extract_ip_port(struct sockaddr const* addr, std::string* host,unsigned short* port) {
    if (addr->sa_family == AF_INET) { //IPv4
        struct sockaddr_in const* ipv4 = reinterpret_cast<struct sockaddr_in const*>(addr);

        char temp[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &ipv4->sin_addr, temp, INET_ADDRSTRLEN);
        *host = temp;

        *port = ntohs(ipv4->sin_port); //<---- ##### WARNING HERE #####
    } else { //IPv6
        struct sockaddr_in6 const* ipv6 = reinterpret_cast<struct sockaddr_in6 const*>(addr);

        char temp[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &ipv6->sin6_addr, temp, INET6_ADDRSTRLEN);
        *host = temp;

        *port = ntohs(ipv6->sin6_port); //<---- ##### WARNING HERE #####
    }
}

问题是对ntohs(...)的调用会产生类似的内容:

<file>:<line>:<char>: warning: conversion to "unsigned int" from "int" may change the sign
of the result [-Wsign-conversion]
    *port = ntohs(ipv6->sin6_port); //<---- ##### WARNING HERE #####
            ^

从上面链接的文档中可以看出,ntohs(...)有一个重载,它接受并返回一个unsigned short。由于portipv4->sin_portipv6->sin6_port都是这样,因此不应发生此警告。所以我的问题是:发生了什么

g ++版本为5.3.0-3ubuntu1~14.04,系统基于ARMv7。我没有能够在x86或x86-64上重现这一点,所以我也标记它

1 个答案:

答案 0 :(得分:1)

这似乎是与语句表达式和C ++相关的问题。这是一个展示行为的简单程序。

int main(void)
{
  unsigned int port =
               (__extension__ ({ unsigned short int __bsx = 
                  (unsigned short int) (0x8345u);
               ((unsigned short int)((((__bsx) >> 8) & 0xffu) | 
                   (((__bsx) & 0xffu) << 8))); }));
  return (int)port;

}

我将此命名为'bar.c',这些会发出警告,

gcc -O3 -Wsign-conversion-x c++ baz.c
arm-linux-gnueabi-gcc -O3 -Wsign-conversion -x c++ baz.c

这些没有,

gcc -O3 -Wsign-conversion bar.c
arm-linux-gnueabi-gcc -O3 -Wsign-conversion baz.c

此外,如果删除语句表达式,则任何语言都不会出现警告。例如,

int main(void)
{
    unsigned int port = 0x8345u;
    ((unsigned short int)(((port) >> 8) & 0xffu) | (((port) & 0xffu) << 8));
    return (int)port;
}
  

所以我的问题:发生了什么?

语句表达式与C ++结合使用时存在一些问题。请参阅documentation。尤其是,

  

这些注意事项意味着在设计用于C ++的头文件中使用此表单的语句表达式可能是个坏主意。 (请注意,GNU C库的某些版本包含使用语句表达式的头文件,这些文件表达式恰好会导致此错误。)

所以用'C'编译或接受警告。这可能是标题中的 bug 或g ++。它不是 ARM CPU相关;您只需获得一个不同的头文件,该文件在编译 ARM 时显示问题。

相关:Endian conversion in C++,换句话说__builtin_bswap16