Domanda

Ho trovato questo nel codice su cui sto lavorando al momento e ho pensato che fosse la causa di alcuni problemi che sto riscontrando.

In un'intestazione da qualche parte:

enum SpecificIndexes{
    //snip
    INVALID_INDEX = -1
};

Successivamente, inizializzazione:

nextIndex = INVALID_INDEX;

e usa

if(nextIndex != INVALID_INDEX)
{
    //do stuff
}

Debug del codice, i valori in nextIndex non hanno abbastanza senso (erano molto grandi) e ho scoperto che era stato dichiarato:

unsigned int nextIndex;

Quindi, l'impostazione iniziale su INVALID_INDEX stava sottovalutando int senza segno e impostandolo su un numero enorme. Ho pensato che fosse ciò che stava causando il problema, ma guardando più da vicino, il test

if(nextIndex != INVALID_INDEX)

Si stava comportando correttamente, cioè non ha mai eseguito il corpo dell'if se nextIndex era il "grande + più valore".

È corretto? Come sta succedendo questo? Il valore enum viene castato implicitamente in un int senza segno dello stesso tipo della variabile e quindi viene racchiuso nello stesso modo?

È stato utile?

Soluzione

Sì a tutto. È un codice valido, è anche comunemente usato codice C ++ lato libreria, più nel moderno C ++ (è strano quando lo vedi per la prima volta ma è un modello molto comune nella realtà).

Quindi gli enum sono ints firmati, ma vengono implicitamente lanciati in ints non firmati, ora questo a seconda del compilatore potrebbe dare un avvertimento, ma è ancora molto comunemente usato, tuttavia è necessario eseguire il cast esplicito per renderlo chiaro ai manutentori.

Altri suggerimenti

gli enum possono essere rappresentati da tipi integrali con o senza segno a seconda che contengano valori negativi e come si sente il compilatore. L'esempio qui contiene un valore negativo e quindi deve essere rappresentato da un tipo integrale con segno.

Il confronto di uguaglianza tra tipi firmati e non firmati è sicuro e di solito fa ciò che l'autore intendeva: il valore firmato verrà prima convertito in non firmato e il risultato di ciò è definito dallo standard C ++ ed è intuitivo (almeno è una volta che conosci il tipo di destinazione. Tranne forse se i numeri interi non sono un complemento a due. Quindi forse non è così intuitivo, ma normalmente non causa problemi.

È più probabile che il confronto degli ordini provochi errori. Ad esempio:

SpecificIndexes value = INVALID_VALUE;
return (value >= 0);

restituisce false, ma:

unsigned int value = INVALID_VALUE;
return (value >= 0);

restituisce vero. A volte l'autore non apprezzerà la differenza, soprattutto se il tipo di "valore" non è così evidente nel punto di utilizzo. Il compilatore potrebbe anche avvertire del secondo esempio, perché (value > = 0) è una tautologia.

In effetti, -1 viene implicitamente proiettato al suo valore non firmato equivalente quando viene assegnato a nextValue. L'equivalente unsigned è il valore con la stessa rappresentazione bit per bit (che è 111111111111 ..., questo è il valore massimo senza segno).

In seguito, nella dichiarazione di confronto, accade un altro cast implicito.

Quindi funziona ora, ma potrebbe causare problemi in futuro. Non è mai una buona idea mescolare valori firmati e non firmati.

Sì, credo che gli enumerati siano firmati. Cambia

unsigned int nextIndex;

a

int nextIndex;

e il tuo programma dovrebbe funzionare.

Lo standard C ++ consente a un'implementazione di usare un tipo firmato per gli enum ma non lo richiede. Pertanto, in generale non si può presumere che sia sicuro inserire numeri negativi in ??un enum.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top