Avviso del compilatore (livello 2) C4146

Operatore unario meno applicato al tipo senza segno, risultato ancora senza segno

I tipi senza segno possono contenere solo valori non negativi, quindi unario meno (negazione) in genere non ha senso se applicato a un tipo senza segno. Sia l'operando che il risultato sono non negativi.

Osservazioni:

Quando si esprime un valore letterale intero negativo, l'oggetto - davanti al valore viene analizzato come operatore di negazione unario. Il compilatore applica l'operatore dopo l'analisi del valore numerico. Se il valore numerico rientra nell'intervallo di un tipo integer senza segno, ma non nel tipo intero con segno corrispondente, il compilatore interpreta il valore come senza segno. Un valore senza segno viene modificato dall'operatore di negazione unario.

Questo avviso si verifica spesso quando si tenta di esprimere il valore minimo int , -2147483648 o il valore minimo long long , -9223372036854775808. Questi valori non possono essere scritti rispettivamente come -2147483648 o -9223372036854775808ll. Il motivo è che il compilatore elabora l'espressione in due fasi: prima analizza il valore numerico, quindi applica l'operatore di negazione. Ad esempio, quando il compilatore analizza -2147483648, segue questa procedura:

  1. Il numero 2147483648 viene valutato. Poiché è maggiore del valore massimo int di 2147483647, ma rientra ancora in un unsigned intoggetto , il tipo di 2147483648 è unsigned int.

  2. Unario meno viene applicato al valore senza segno, con un risultato senza segno, che si verifica anche 2147483648.

Il tipo non firmato del risultato può causare un comportamento imprevisto. Se il risultato viene usato in un confronto, è possibile usare un confronto senza segno, ad esempio quando l'altro operando è .int

È possibile evitare C4146 usando INT_MIN o LLONG_MIN da <limits.h> o dall'equivalente C++, <climits>. Questi valori hanno tipi firmati.

L'opzione del /sdl compilatore (Abilita controlli di sicurezza aggiuntivi) eleva questo avviso a un errore.

Esempio

L'esempio seguente illustra il comportamento imprevisto che può verificarsi quando il compilatore genera l'avviso 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);
}

In questo esempio il compilatore considera -9223372036854775808ll senza segno anche se il valore letterale ha un ll suffisso e viene applicato l'operatore di negazione. Per eseguire il confronto, il compilatore promuove automaticamente l'accesso < a i unsigned long long int. La seconda riga prevista, 1 is greater than the most negative long long int, non viene stampata perché ((unsigned long long int)1) > 9223372036854775808ull è false.

Per correggere l'esempio, includere <climits> e modificare -9223372036854775808ll in LLONG_MIN.

Vedi anche

Operatore di negazione unario (-)