編譯器警告 (層級 2) C4146
一元減號運算子套用 unsigned 類型,所得的結果也會是 unsigned 類型
不帶正負號的類型只能保存非負值,因此一元減號(負號)在套用至不帶正負號的類型時通常沒有意義。 操作數和結果都是非負數。
備註
當您表示負整數常值時, -
值前面的 會剖析為 一元否定 運算符。 編譯程式會在剖析數值之後套用 運算元。 如果數值符合無符號整數類型的範圍,但不符合對應的帶正負號整數類型,編譯程式會將值解譯為不帶正負號。 一元負號運算子不會變更不帶正負號的值。
當您嘗試表示最小值 int
-2147483648 或最小值 long long
-9223372036854775808 時,通常會發生此警告。 這些值不能分別寫入為 -2147483648 或 -9223372036854775808ll。 原因是編譯程式會以兩個階段處理表達式:首先,它會剖析數值,然後套用否定運算符。 例如,當編譯程式剖析 -2147483648時,它會遵循下列步驟:
會評估2147483648數目。 因為它大於2147483647的最大值
int
,但仍符合unsigned int
,所以 2147483648 的類型為unsigned int
。一元減號會套用至不帶正負號的值,併產生不帶正負號的結果,這也會發生2147483648。
結果的不帶正負號類型可能會導致非預期的行為。 如果在比較中使用結果,則當另一個操作數是 int
時,可能會使用不帶正負號的比較。
您可以使用 或 LLONG_MIN
C++對等<climits>
的 或 ,<limits.h>
來避免 C4146INT_MIN
。 這些值具有帶正負號的類型。
/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
。