ARM上有`ntohs(…)`的`Wsign conversion`错误?

ARM上有`ntohs(…)`的`Wsign conversion`错误?,arm,c++,g++,cross-platform,Arm,C++,G++,Cross Platform,下面是一个示例,显示了我的代码的简化版本,它仍然可以做一些有用的事情: //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 ==

下面是一个示例,显示了我的代码的简化版本,它仍然可以做一些有用的事情:

//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(…)
有一个重载,它接受并返回一个无符号的short。由于
端口
ipv4->sin_端口
ipv6->sin6_端口
都是这些,因此不应出现此警告。所以我的问题是:发生了什么事


g++版本为
5.3.0-3ubuntu1~14.04
,系统基于ARMv7。我在x86或x86—64上无法复制这个,所以我也在标记它。

这似乎是一个与语句表达式和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;

}
这些没有,

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;
}
int main(无效)
{
无符号整数端口=0x8345u;

((无符号短整数)((端口>>8)和0xffu)((端口)和0xffu)提示:您可以使用<代码> -e <代码>选项来获得预处理的输出,以生成一个更简洁的例子。只检查“代码> -E<代码>输出的结束。我用这个来找到ARM版本的代码> NtoHS < /C++ >,如我的回答。这个问题似乎与“按位移位和/或”和C++流/引用问题有关。
(((uuu-bsx)>>8)
替换为
(无符号短)(((uuu-bsx)>>8)
,那么使用gcc两种语言都没有警告。我只需使用“bswap”函数并继续。我使用
gcc
作为5.2.1-22ubuntu2和
arm linux gnueabi-gcc
作为5.2.1-22ubuntu1.Ah,所以这里的关键组件是
ntohs(…)
实际上是一个宏(最终位于
netinet/in.h:401
),它调用语句表达式(最终位于
bits/byteswap-16.h:24
)我不知道,我认为这是图书馆里的一个错误,尽管它不允许在C++中不兼容地工作。我同意,但是你想编辑页眉/库吗?我考虑向GCC/G++或GleBC人提交一个bug。但是,你可以在C++中使用一个替换的字节交换,或者使用“C”。我觉得问题可能是Gcc/g++,因为返回值<代码> {V}<代码>是(正确的)代码>无符号短int < /代码>。当然,我不确定这意味着什么;我从来没有使用过语句表达式,而且(它们是不可移植的)。我不打算这么做。我最终使用了我的库中已有的函数,正是为了这个目的;我不知道为什么我没有首先使用它。我想其中一个编译器内部函数,带有适当的预处理器保护,也可以工作。
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;
}