一元減號運算子套用 unsigned 類型,所得的結果也會是 unsigned 類型
備註
無符號類型只能持有非負值。 因此,套用至不帶正負號的類型時,一元減號(否定)通常沒有意義。 操作數和結果都是非負數。
當您表達負整數常值時,- 前面的符號會被解析為 一元負號 運算符。 編譯程式會在剖析數值之後套用 運算元。 如果數值符合無符號整數類型的範圍,但不符合對應的帶正負號整數類型,編譯程式會將值解譯為不帶正負號。
當您嘗試表示最小值 int -2147483648 或最小值 long long -9223372036854775808 時,通常會發生此警告。 這些值無法寫入為 -2147483648 或 -9223372036854775808ll。 原因是編譯程式會以兩個階段處理表達式:首先,它會剖析數值,然後套用否定運算符。 例如,當編譯程式剖析 -2147483648時,它會遵循下列步驟:
- 會評估2147483648數目。 因為它大於2147483647的最大值
int,但仍符合unsigned int,所以 2147483648 的類型為unsigned int。 - 一元減號會套用至不帶正負號的值,併產生不帶正負號的結果,這也會發生2147483648。
結果的不帶正負號類型可能會導致非預期的行為。 如果在比較中使用結果,則當另一個操作數是 int時,可能會使用不帶正負號的比較。
您可以使用或從INT_MIN中選擇LLONG_MIN,或使用等效的C++選項<limits.h>,以避免<climits>。 這些值具有帶正負號的類型。
[啟用其他安全性檢查] 編譯程序選項會將/sdl這個警告提升為錯誤。
範例
下列範例示範編譯器產生警告 C4146 時可能發生的非預期行為:
// C4146.cpp
// compile with: /W2
#include <iostream>
void check(int i)
{
if (i > -9223372036854775808ll) // C4146
std::cout << i << " is greater than the most negative long long int.\n";
}
int main()
{
check(-100);
check(1);
}
在此範例中,編譯程式會考慮 -9223372036854775808ll不帶正負號,即使常值具有 ll 後綴,而且會套用否定運算符。 為了進行 < 比較,編譯程式會以無訊息方式將已簽署 i 的 升級為 unsigned long long int。 預期的第二行 1 is greater than the most negative long long int不會列印,因為 ((unsigned long long int)1) > 9223372036854775808ull 為 false。
若要修正範例,請將 -9223372036854775808ll 包含 <climits> 並變更為 LLONG_MIN。