Upozornění kompilátoru (úroveň 2) C4146
unární mínus operátor použitý na nepodepsaný typ, výsledek je stále nepodepsaný
Nepodepsané typy můžou obsahovat pouze nezáporné hodnoty, takže unární minus (negation) obvykle při použití u nepodepsaného typu nedává smysl. Operand i výsledek jsou nezáporné.
Poznámky
Při vyjádření záporného celočíselného literálu -
se před hodnotou parsuje jako operátor unární negace . Kompilátor použije operátor po parsování číselné hodnoty. Pokud se číselná hodnota vejde do rozsahu celočíselného typu bez znaménka, ale ne odpovídající typ celého čísla se znaménkem, kompilátor interpretuje hodnotu jako nepodepsanou. Unsigned value is unchanged by unary negation operator.
K tomuto upozornění často dochází, když se pokusíte vyjádřit minimální int
hodnotu, -2147483648 nebo minimální long long
hodnotu , -9223372036854775808. Tyto hodnoty nelze zapsat jako -2147483648 nebo -9223372036854775808ll. Důvodem je to, že kompilátor zpracovává výraz ve dvou fázích: nejprve parsuje číselnou hodnotu a pak použije operátor negace. Když například kompilátor parsuje -2147483648, postupuje takto:
Vyhodnotí se číslo 2147483648. Protože je větší než maximální
int
hodnota 2147483647, ale přesto se vejde dounsigned int
, typ 2147483648 jeunsigned int
.Unární mínus se použije na hodnotu bez znaménka s výsledkem bez znaménka, který se také stane 2147483648.
Nepodepsaný typ výsledku může způsobit neočekávané chování. Pokud je výsledek použit v porovnání, pak se může použít nepodepsané porovnání, například když druhý operand je .int
C4146 se můžete vyhnout použitím INT_MIN
nebo LLONG_MIN
ekvivalentem <limits.h>
jazyka C++ nebo z jazyka C++. <climits>
Tyto hodnoty mají podepsané typy.
Možnost kompilátoru /sdl
(Povolit další kontroly zabezpečení) zvýší toto upozornění na chybu.
Příklad
Následující ukázka ukazuje neočekávané chování, ke kterému může dojít při generování upozornění C4146 kompilátoru:
// 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);
}
V tomto příkladu kompilátor považuje -9223372036854775808ll bez znaménka, i když literál má ll
příponu a použije se operátor negace. Aby bylo <
porovnání, kompilátor bezobslužně podporuje podepsáno i
.unsigned long long int
Očekávaný druhý řádek 1 is greater than the most negative long long int
, není vytištěn, protože ((unsigned long long int)1) > 9223372036854775808ull
je false.
Pokud chcete tento příklad opravit, zahrňte <climits>
a změňte -9223372036854775808ll na LLONG_MIN
.