2011-12-19 23 views
5

當我嘗試使用啓用了警告級別/ W4的Visual Studio 2010 C++編譯器(X86)編譯以下C++程序時,出現簽名/未簽名不匹配警告標記線。C++:僅當使用無符號類型時出現簽名/未簽名不匹配

#include <cstdio> 
#include <cstdint> 
#include <cstddef> 

int main(int argc, char **argv) 
{ 
    size_t idx = 42; 
    uint8_t bytesCount = 20; 

    // warning C4389: '==' : signed/unsigned mismatch 
    if (bytesCount + 1 == idx) 
    { 
     printf("Hello World\n"); 
    } 

    // no warning 
    if (bytesCount == idx) 
    { 
     printf("Hello World\n"); 
    } 
} 

這使我困惑,因爲我只使用無符號類型。由於比較

bytesCount == idx 

不會引起這樣的警告,它可能與這裏發生的一些奇怪的隱式對話有關。

因此:我得到這個警告的原因是什麼,以及這個對話發生了什麼規則(如果這是原因)?

回答

5

1int。積分算術表達式的類型取決於所涉及的類型。在這種情況下,您有unsigned類型和signed類型,其中unsigned類型小於signed類型。這個屬於C++標準下的表達式(第5.10 [EXPR]):

否則,如果操作數的與符號整型類型可以 代表所有的操作數的類型的值與無符號 整數類型,無符號整數類型的操作數應爲 ,轉換爲帶符號整數類型的操作數的類型。

也就是說,表達式bytesCount + 1的類型是int,它是默認簽名的。

9

1是一個有符號的文字。嘗試bytesCount + 1U。

編譯器可能產生由於添加符號和無符號的值(bytesCount + 1)

3

的符號類型的一個臨時值由於1是類型int表達bytesCount + 1int(簽名)。

在當型比int更小的數學表達式被晉升爲int被使用,因此,即使+ bytesCountbytesCount + bytesCount被認爲int和不uint8_t事實(而bytesCount + 1U是因爲,一個unsigned intint較大) 。

following program輸出true三次。

#include <iostream> 

int main() 
{ 
    unsigned short s = 1; 
    std::cout << (&typeid(s + 1U) == &typeid(1U)) << std::endl; 
    std::cout << (&typeid(+ s) == &typeid(1)) << std::endl; 
    std::cout << (&typeid(s + s) == &typeid(1)) << std::endl; 
} 
1

其他答案已經告訴你,bytesCount + 1被解釋爲signed int。不過,我想補充一點,在bytesCount == idx,bytesCount解釋爲signed int。從概念上講,它首先轉換爲signed int,之後它只轉換爲unsigned int。你的編譯器不會對此提出警告,因爲它有足夠的信息來知道沒有問題。轉換爲signed int不可能使bytesCount爲負。比較bytesCount + 1是同樣有效的,同樣安全,但只是稍微複雜一些,使編譯器不再認爲它是安全的。

+0

如何告訴編譯器不要警告我有關這樣的問題,如果從程序代碼中可以清楚地看到比較是安全的,但我不想禁用整個文件的警告,並且我不想讓代碼變得醜陋避免它。 是否存在任何方式來實現這一目標? – Arkady 2016-11-10 13:21:00

+0

@Arkady如果編譯器被配置爲警告代碼,您不想更改代碼(因爲它會更醜),並且您不想更改編譯器的配置(因爲它會抑制有用的警告也是如此),你不會留下很多選擇。我認爲你還沒有排除的唯一選擇就是編寫黑客程序來改進它的分析。 – hvd 2016-11-11 14:27:57