Question

J'ai trouvé cela dans le code sur lequel je travaille en ce moment et je pensais que c'était la cause de certains problèmes que je rencontrais.

Dans un en-tête quelque part:

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

Puis plus tard - initialisation:

nextIndex = INVALID_INDEX;

et utiliser

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

Lors du débogage du code, les valeurs de nextIndex n’avaient pas vraiment de sens (elles étaient très grandes) et j’ai trouvé qu’il était déclaré:

unsigned int nextIndex;

Ainsi, le paramètre initial sur INVALID_INDEX sous-traitait le unsigned int et le fixait à un nombre énorme. Je pensais que c’était la cause du problème, mais en regardant de plus près, le test

if(nextIndex != INVALID_INDEX)

se comportait correctement, c’est-à-dire qu’il n’exécutait jamais le corps de if lorsque nextIndex était la "grande + valeur".

Est-ce correct? Comment ça se passe? La valeur enum est-elle implicitement convertie en un unsigned int du même type que la variable, et est-il donc encapsulé de la même manière?

Était-ce utile?

La solution

Oui à tout. C’est un code valide, c’est aussi un code C ++ communément utilisé du côté de la bibliothèque, surtout dans le C ++ moderne (c’est étrange quand on le voit pour la première fois mais c’est un motif très courant en réalité).

Ensuite, les énumérations sont des ints signés, mais ils sont implicitement convertis en ints non signés. Désormais, cela dépend de votre compilateur et peut vous donner un avertissement, mais il est encore très utilisé, mais vous devez explicitement le faire pour le mettre clairement à la disposition des mainteneurs.

Autres conseils

Les énumérations

peuvent être représentées par des types intégraux signés ou non signés, selon qu'ils contiennent ou non des valeurs négatives et ce que ressent le compilateur. L'exemple ici contient une valeur négative et doit donc être représenté par un type intégral signé.

La comparaison d'égalité entre les types signés et non signés est sûre et correspond généralement à l'intention de l'auteur: la valeur signée est d'abord convertie en non signée. Le résultat de cette opération est défini par la norme C ++ et est intuitif (du moins, il C’est une fois que vous connaissez le type de destination. Sauf peut-être si les entiers ne sont pas complémentaires de deux. Alors peut-être pas aussi intuitif, mais cela ne pose normalement pas de problèmes).

La comparaison des commandes est plus susceptible de générer des erreurs. Par exemple:

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

renvoie false, mais:

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

retourne vrai. Parfois, l'auteur n'appréciera pas la différence, surtout si le type de "valeur" n'est pas aussi évident au moment de l'utilisation. Le compilateur peut toutefois vous avertir du deuxième exemple car (valeur > = 0) est une tautologie.

En fait, -1 est implicitement converti en sa valeur non signée équivalente lorsqu'il est affecté à nextValue. L'équivalent non signé est la valeur avec la même représentation au niveau du bit (c'est-à-dire 111111111111 ..., c'est la valeur maximale non signée).

Plus tard, dans l'instruction de comparaison, une autre conversion implicite se produit.

Cela fonctionne donc maintenant, mais pourrait poser problème à l'avenir. Ce n’est jamais une bonne idée de mélanger des valeurs signées et non signées.

Oui, je crois que les enums sont signés. Changer

unsigned int nextIndex;

à

int nextIndex;

et votre programme devrait fonctionner.

Le standard C ++ permet à une implémentation d'utiliser un type signé pour les énumérations, mais ne l'exige pas. Par conséquent, vous ne pouvez généralement pas supposer qu’il est prudent de placer des nombres négatifs dans une énumération.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top