Avertissement du compilateur (niveau 2) C4146
opérateur moins unaire appliqué à un type non signé, le résultat sera non signé
Les types non signés ne peuvent contenir que des valeurs non négatives. Par conséquent, unaire moins (négation) n’a généralement pas de sens lorsqu’ils sont appliqués à un type non signé. L’opérande et le résultat ne sont pas négatifs.
Notes
Lorsque vous exprimez un littéral entier négatif, l’avant -
de la valeur est analysée en tant qu’opérateur de négation unaire. Le compilateur applique l’opérateur après avoir analysé la valeur numérique. Si la valeur numérique correspond à la plage d’un type entier non signé, mais pas au type entier signé correspondant, le compilateur interprète la valeur comme non signée. Une valeur non signée est inchangée par l’opérateur de négation unaire.
Cet avertissement se produit souvent lorsque vous essayez d’exprimer la valeur minimale int
, -2147483648 ou la valeur minimale long long
, -9223372036854775808. Ces valeurs ne peuvent pas être écrites en tant que -2147483648 ou -9223372036854775808ll, respectivement. La raison est que le compilateur traite l’expression en deux étapes : d’abord, il analyse la valeur numérique, puis applique l’opérateur de négation. Par exemple, lorsque le compilateur analyse -2147483648, il suit les étapes suivantes :
Le nombre 2147483648 est évalué. Étant donné qu’il est supérieur à la valeur maximale
int
de 2147483647, mais s’inscrit toujours dans ununsigned int
, le type de 2147483648 estunsigned int
.Unaire moins est appliqué à la valeur non signée, avec un résultat non signé, qui se produit également 2147483648.
Le type non signé du résultat peut entraîner un comportement inattendu. Si le résultat est utilisé dans une comparaison, une comparaison non signée peut être utilisée, par exemple lorsque l’autre opérande est un int
.
Vous pouvez éviter L’utilisation INT_MIN
ou LLONG_MIN
l’équivalent <limits.h>
C++ de C4146. <climits>
Ces valeurs ont des types signés.
L’option /sdl
(Activer des vérifications de sécurité supplémentaires) l’option du compilateur élève cet avertissement à une erreur.
Exemple
L’exemple suivant illustre le comportement inattendu qui peut se produire lorsque le compilateur génère l’avertissement 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);
}
Dans cet exemple, le compilateur considère -9223372036854775808ll non signé même si le littéral a un ll
suffixe et que l’opérateur de négation est appliqué. Pour effectuer la <
comparaison, le compilateur promeut silencieusement la signature i
à unsigned long long int
. La deuxième ligne attendue, 1 is greater than the most negative long long int
n’est pas imprimée, car ((unsigned long long int)1) > 9223372036854775808ull
elle a la valeur false.
Pour corriger l’exemple, incluez <climits>
et remplacez -9223372036854775808ll par LLONG_MIN
.