2016-01-25 31 views
1

這裏是一個SSCCE,表現出我的代碼的簡化版本,仍然沒有一些有用的東西:ARM上的`ntohs(...)`錯誤`-Wsign-conversion`錯誤?

//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上重現這一點,所以我也標記它

+0

提示:您可以使用'-E'選項來獲得預處理輸出以製作更簡潔的示例。只要檢查'-E'輸出的結尾。我用這個來找到ARM版本的'ntohs',就像我的答案一樣。 –

回答

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」編譯或接受警告。這可以是標題中的錯誤或g ++。它不是ARM CPU相關;你只是得到一個不同的頭文件,它顯示編譯爲ARM時的問題。

相關:Endian conversion in C++,換句話說__builtin_bswap16

+0

這個問題似乎與'按位移/和'和C++流/參考問題有關。如果用((unsigned short)((__ bsx)>> 8)'替換'((__bsx)>> 8)',那麼兩種語言都不會有警告。我只是使用'bswap'功能,繼續前進。 –

+0

我使用'gcc'作爲5.2.1-22ubuntu2和'arm-linux-gnueabi-gcc'作爲5.2.1-22ubuntu1。 –

+0

啊,所以這裏的關鍵組件是'ntohs(...)'實際上是一個調用語句表達式的宏(最終在'netinet/in.h:401'處)(最終以「bits/byteswap-16」 h:24')。我不知道 - 儘管有免責聲明,但我認爲這是圖書館中的一個錯誤。沒有理由不能在C++中兼容。 – imallett