Pourquoi int8_t et l’entrée utilisateur via cin affichent-ils un résultat étrange?

Un petit morceau de code me rend fou, mais j’espère que vous pourrez m’empêcher de sauter par la fenêtre. Regardez ici:

#include  #include  int main() { int8_t i = 65; int8_t j; std::cout << "i = " << i << std::endl; // the 'A' is ok, same as uchar std::cout << "Now type in a value for j (use 65 again): " <> j; std::cout << "j = " << j << std::endl; if (i != j) std::cout << "What is going on here?????" << std::endl; else std::cout << "Everything ok." << std::endl; return 0; } 

Si j’utilise int au lieu de int8_t tout va bien. J’ai besoin de cela en tant qu’entiers unsigned integers 8 bits, pas plus gros. Et d’ailleurs. avec unsigned char c’est le même comportement – bien sûr – comme avec int8_t .

Quelqu’un avec un indice?

int8_t est un typedef pour un type entier ayant les caractéristiques requirejses: représentation pure en complément à 2, pas de bits de remplissage, taille exacte de 8 bits.

Pour la plupart des compilateurs (peut-être tous), cela signifie qu’il s’agira d’un typedef pour un caractère signed char (en raison d’un caprice dans la définition du terme type entier signé , il ne peut pas s’agir d’un typedef pour un caractère simple, même si ce caractère est signé).

L’opérateur >> traite spécialement les types de caractères. La lecture d’un caractère lit un seul caractère saisi, et non une séquence de caractères représentant une valeur entière en décimal. Donc, si le caractère suivant est '0' , la valeur lue sera la valeur '0' , probablement 48.

Etant donné qu’une typedef crée un alias pour un type existant, et non un nouveau type distinct, l’opérateur >> n’a aucun moyen de savoir que vous souhaitez traiter int8_t comme un type entier plutôt que comme un type de caractère.

Le problème est que dans la plupart des implémentations, il n’y a pas de type entier 8 bits qui ne soit pas un type de caractère.

La seule solution consiste à lire dans une variable int puis à convertir en int8_t (avec des vérifications de plage si vous en avez besoin).

Par ailleurs, int8_t est un type signé ; le type non signé correspondant est uint8_t , dans la plage 0..255.

( CHAR_BIT > 8 considération: si CHAR_BIT > 8 , ce qui est autorisé par la norme, alors ni int8_t ni uint8_t ne seront définis.)

int8_t et uint8_t sont presque certainement des types de caractères ( Int8_t et uint8_t sont-ils destinés à se comporter comme un caractère? ), donc std::cin >> j lira un seul caractère à partir de stdin et l’interprétera comme un caractère et non comme un nombre.

int8_t est probablement identique à char , ce qui signifie que cin >> j lit simplement un seul caractère ( '6' ) à partir de l’entrée et le stocke dans j .

int8_t est défini comme un nom de typedef pour le caractère signed char . Ainsi, l’ operator >> utilisé avec un object de type int8_t se comporte de la même manière qu’il le serait pour un object de type signed char

Les types _t ne sont pas des types de première classe, mais des alias de type typedef . int8_t certaines contraintes. int8_t exemple, int8_t est un type pouvant stocker une valeur signée sur 8 bits.

Sur la plupart des systèmes, cela signifie qu’ils sont typedef et char . Et comme il s’agit d’un typedef et non d’un type de première classe, vous cin.operator<<(char) et cin.operator>>(char) .

Lorsque vous entrez "65", cin.operator>>(char) consum le '6' et place sa valeur ascii, 54, dans la variable j .

Pour contourner ce problème, vous devrez utiliser un type différent, la méthode la plus simple étant probablement d’utiliser un type entier plus grand et d’appliquer des contraintes, puis d’abattre:

 int8_t fetchInt8(const char* prompt) { int in = 0; for ( ; ; ) { // endless loop. std::cout << prompt << ": "; std::cin >> in; if (in >= std::numeric_limits::min() && in <= std::numeric_limits::max()) { std::cout << "You entered: " << in << '\n'; // exit the loop break; } std::cerr << "Error: Invalid number for an int8\n"; } return static_cast(in); } 

Notez que int8_t est signé, ce qui signifie qu'il stocke -128 à +127. Si vous souhaitez uniquement des valeurs positives, utilisez le type uint8_t.