Sont int8_t et u_int8_t prévu pour être de type char types?
Compte tenu de cette C++11 programme, dois-je m'attendre à voir un certain nombre ou une lettre? Ou ne pas faire hauteur des attentes?
#include <cstdint>
#include <iostream>
int main()
{
int8_t i = 65;
std::cout << i;
}
La norme de préciser si ce type peuvent ou pourront être un type de caractère?
- int selon specifcations doit au moins 16bits
uint8_t
est un type entier, pas un type de caractère. J'attends des chiffres, pas de lettres. Il ressemble à un autre comité C++ faux pas (GCC 6.3.1-1 imprime comme des caractères). Le comité a partiellement droit àstd::byte
.std::byte
ne s'imprime pas comme un type de caractère (à l'heure actuelle, il n'imprime pas du tout. J'espère que ça sera corrigé dans le futur).
Vous devez vous connecter pour publier un commentaire.
Du § 18.4.1 [cstdint.syn] du C++0x FDIS (N3290),
int8_t
est une option de définition de type qui est spécifié comme suit:§ 3.9.1 [de base.fondamentaux] états:
§ 3.9.1 déclare également:
Il est tentant de conclure que
int8_t
peut être une définition de type dechar
fournichar
objets prennent des valeurs signées; cependant, ce n'est pas le cas commechar
n'est pas parmi la liste des entier signé types (standard et étendu éventuellement signé types d'entiers). Voir aussi Stephan T. Lavavej commentaires surstd::make_unsigned
etstd::make_signed
.Donc, soit
int8_t
est un typedef designed char
ou c'est une longue signée de type entier dont les objets occupent exactement 8 bits de stockage.Pour répondre à votre question, cependant, vous ne devriez pas faire des hypothèses. Parce que les fonctions des deux formes
x.operator<<(y)
etoperator<<(x,y)
ont été définis, § 13.5.3 [plus.binaire] dit que nous référer au § 13.3.1.2 [plus.match.oper] pour déterminer l'interprétation destd::cout << i
. § 13.3.1.2 à son tour, dit que la mise en œuvre sélectionne à partir de la série de fonctions candidates selon § 13.3.2 et § 13.3.3. Nous abordons ensuite le § 13.3.3.2 [plus.ics.classement] pour déterminer que:template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)
modèle sera appelé siint8_t
est une Correspondance Exacte poursigned char
(c'est à dire une définition de type designed char
).int8_t
serait promuint
et labasic_ostream<charT,traits>& operator<<(int n)
membre de la fonction est appelée.Dans le cas de
std::cout << u
pouru
unuint8_t
objet:template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)
modèle sera appelé siuint8_t
est une Correspondance Exacte pourunsigned char
.int
peut représenter toutesuint8_t
valeurs, lauint8_t
serait promuint
et labasic_ostream<charT,traits>& operator<<(int n)
membre de la fonction est appelée.Si vous voulez imprimer un caractère, la plus sûre et la plus claire de l'option est:
Et si vous souhaitez toujours l'impression d'un nombre:
typedef char int8_t
": je crois, ce n'est pas vrai parce quechar
est un type entier, mais ce n'est pas un entier signé, même si elle a un signe. Voir mon post pour une (on l'espère corriger) explication sur cette (plutôt déroutant) de la terminologie.char
dans la liste des signé les types integer ou unsigned integer types parce que la Norme permetchar
objets à revêtir signés ou non des valeurs. Donc, je ne suis pas d'accord avec votre point de vue que juste parce quechar
n'est pas répertorié dans la liste des signé les types integer, ce qui signifie qu'unchar
n'est pas un signé de type integer même si elle prend des valeurs signées parce que le Standard de vous ne pouvez pas inclurechar
dans une liste de signé les types integer ou unsigned integer types.std::make_signed<int8_t>::type
devrait être identiqueint8_t
parce queint8_t
est spécifié comme un signé de type integer. Par conséquent,int8_t
ne peut pas être untypedef
dechar
même sichar
objets prennent des valeurs signées.int8_t
est exactement 8 bits de large (si elle existe).Le seul entier prédéfini types qui peuvent être de 8 bits sont
char
,unsigned char
, etsigned char
. Les deuxshort
etunsigned short
doivent être d'au moins 16 bits.Donc
int8_t
doit être un typedef poursigned char
ou de la plainechar
(le dernier si simplechar
est signé).Si vous souhaitez imprimer une
int8_t
valeur comme un nombre entier plutôt que comme un personnage, vous pouvez convertir explicitement àint
.En principe, un compilateur C++ pourrait définir un 8-bit étendu de type entier (peut-être appelé quelque chose comme
__int8
), et de faireint8_t
un typedef pour elle. La seule raison pour laquelle je peux penser à faire serait d'éviter de faire desint8_t
un type de caractère. Je ne sais pas du tout compilateurs C++ qui ont effectivement fait cela.Les deux
int8_t
et étendu les types d'entiers ont été introduites en C99. Pour le C, il n'y a pas de raison particulière de définir une 8-bits étendu de type entier lors de lachar
types sont disponibles.Mise à JOUR:
Je ne suis pas entièrement à l'aise avec cette conclusion.
int8_t
etuint8_t
ont été introduites en C99. En C, il n'est pas particulièrement question de savoir s'ils sont de types de caractères ou pas; il n'y a pas des opérations pour lesquelles la distinction fait une vraie différence. (Mêmeputc()
, le plus faible niveau de sortie de caractères de routine en C standard, prend le caractère à imprimer comme unint
argument).int8_t
, etuint8_t
, si ils sont définis, sera presque certainement être définis comme des types de caractères -- mais les types de caractères sont juste des petits types d'entiers.C++ fournit des versions surchargées de
operator<<
pourchar
,signed char
, etunsigned char
, de sorte questd::cout << 'A'
etstd::cout << 65
produire de très différent de sortie. Plus tard, C++ adoptéint8_t
etuint8_t
, mais de telle manière que, comme en C, ils sont presque certainement les types de caractères. Pour la plupart des opérations, cela n'a pas d'importance, pas plus qu'il n'en C, mais pourstd::cout << ...
il y a une différence, puisque c':sera probablement imprimer la lettre
A
plutôt que le nombre65
.Si vous souhaitez un comportement cohérent, ajouter un plâtre:
Je pense que la racine du problème est qu'il manque quelque chose à partir de la langue: très étroit types d'entiers qui ne sont pas de types de caractères.
Comme pour le intention, je pourrait spéculer que les membres du comité, soit n'ont pas réfléchir à la question, ou décidé qu'il n'était pas utile de traiter. On pourrait dire (et je) que les avantages de l'ajout de la
[u]int*_t
les types de la norme l'emporte sur les inconvénients de leur un comportement bizarre avecstd::cout << ...
.short
(autres qu'à moins de la taille designed char
) et je ne pouvais pas le trouver - pourriez-vous fournir une référence?<limits.h>
, y comprisSHRT_MIN <= -32767
,SHRT_MAX >= +32767
, etUSHRT_MAX >= 65535
typedef
int8_t
à un non-standard de mise en œuvre de type défini (et peut bien sur ces quelques plates-formes qui utilisent un 16 bitschar
). Je pense que le C++11 est manquant quelques éclaircissements nécessaires sur la façon dont cesstdint.h
types devrait résoudre dans les surcharges. Je soupçonne que la façon dont ces types de peut-match pour la résolution de surcharge serait définie par l'implémentation.int8_t
- à moins que, je suppose, c'est juste pour éviter de faireint8_t
un type de caractère.char
type est de 16 bits. Même dans ce cas, si il y avait des surcharges pour les deuxsigned char
etint
, qui aurait la préférence de surcharge?char
est de 16 bits, puisCHAR_BIT==16
, et un octet est, par définition, 16 bits. En dehors de champs de bits, vous ne pouvez pas avoir un type entier plus petit que 1 octet. Donc, dans ce cas il n'y aurait pasint8_t
. (Si vous n'êtes pas convaincu, pensez àsizeof (int8_t)
.)int8_t
n'est pas un typedef poursigned char
,ostream::operator<<(char)
est probablement le meilleur match au cours de la résolution de surcharge, et donc, si vous voulez obtenir la sortie de caractères de toute façon.signed char
ouchar
?__int8
vous l'avez mentionné dans votre réponse (par exemple, MSVC en a un). Mais la Normeostream
classe n'a pas la forme d'un opérateur d'insertion de surcharge pour__int8
... donc il va utiliser l'un pourchar
de toute façon.(unsigned) int
(à partir d'un type avec une baisse de conversion rang). Une conversion serait [conv.intégrale]/1, c'est à dire une conversion de tout type entier (y comprischar
). Seulement sichar == uint8_t
, la plus viable fonction doit êtreoperator<< (char)
autant que je sache, d'autreoperator<< (int)
.__int8
type qui n'est pas untypedef
pour unchar
. Cependant, "__int8
type de données est synonyme de typechar
". Voir ici. Vous pouvez le vérifier par la déclaration d'une variable de type__int8
et de voir que le débogueur dit que c'est unchar
. C'est assez déroutant, je dois dire. Je n'ai aucune idée de pourquoi MS a fait.<stdint.h>
, qui a introduitint8_t
et coll. Cela ressemble, plutôt que d'être un typedef,__int8
est une mise en œuvre définies par mot-clé que les noms du même type que lechar
ne, de la même façonint
etsigned
nom du même type.static_cast
ne sont pas d'équivalent dans le dernier exemple (la fonction de style fonte peut légalement jeté constness ou relire)unsigned char
s'exemption de l'aliasing règles, et utiliseuint8_t
à cette fin. Il aurait été utile si c99 a défini un nom commeuinta8_t
pour une 8 bits type d'aliasing soutien, [permettant u_int8_t être un type étendu sans aliasing support], mais depuis, il n'a pas, beaucoup de code utiliseuint8_t
même lorsque l'aliasing de soutien est nécessaire.Je vais répondre à vos questions dans l'ordre inverse.
Réponse courte:
int8_t
estsigned char
dans la plupart des plates-formes populaires (GCC/Intel/Clang sur Linux et Visual Studio sous Windows), mais peut-être autre chose dans d'autres.Le long suit la réponse.
Section 18.4.1 du C++11 Norme donne le synopsis de
<cstdint>
qui comprend les éléments suivantsPlus loin dans le même article, à l'alinéa 2, il est dit
où C norme C99 comme par 1.1/2:
Par conséquent, la définition de
int8_t
se trouve dans la Section 7.18 du standard C99. Plus précisément, C99 Section 7.18.1.1 ditEn outre, la C99 de la Section 6.2.5/4 dit
Enfin, C99 Section 5.2.4.2.1 impose des tailles minimales de la norme entier signé types. À l'exclusion de
signed char
, tous les autres sont au moins 16 bits.Par conséquent,
int8_t
est soitsigned char
ou 8 bits étendu (non standard) entier signé de type.À la fois de la glibc (la bibliothèque C de GNU) et Visual Studio C de la bibliothèque de définir
int8_t
commesigned char
. Intel et Clang, au moins sur Linux, aussi l'utilisation de la libc, et donc, la même chose s'applique à eux. Par conséquent, dans la plupart des plates-formes populairesint8_t
estsigned char
.Réponse courte: Dans la plupart des plates-formes populaires (GCC/Intel/Clang sur Linux et Visual Studio sous Windows), vous allez certainement voir la lettre 'A'. En d'autres plates-formes que vous pouvez obtenir de voir
65
bien. (Merci à Dpj pour le rappeler à moi.)Dans la suite, toutes les références sont pour le C++11 standard (projet actuel, N3485).
L'article 27.4.1 fournit le synopsis de
<iostream>
, en particulier, il dispose de la déclaration decout
:Maintenant,
ostream
est untypedef
pour un modèle de spécialisation debasic_ostream
conformément à l'Article 27.7.1:Section 27.7.3.6.4 fournit la déclaration suivante:
Si
int8_t
estsigned char
alors c'est cette surcharge qui va être appelé. Le même article précise également que l'effet de cet appel est de l'impression du caractère (pas le nombre).Maintenant, considérons le cas où
int8_t
est une extension de type entier signé. Évidemment, la norme ne spécifie pas les surcharges deoperator<<()
pour les types, mais grâce à des promotions et des conversions l'une des surcharges peut accepter l'appel. En effet,int
est d'au moins 16 bits de long et peut représenter toutes les valeurs deint8_t
. Puis de 4,5/1 donne queint8_t
peut être promu àint
. D'autre part, de 4,7/1 et 4,7/2 donne queint8_t
peut être converti àsigned char
. Enfin, 13.3.3.1.1 rendements que la promotion est favorisée par rapport à la conversion au cours de la résolution de surcharge. Par conséquent, la surcharge suivante (déclarée dans 23.7.3.1)sera appelée. Cela signifie que, ce code
imprime
65
.Mise à jour:
1. Corrigé le post suivant Dpj's commentaire.
2. Ajouté les commentaires suivants sur la possibilité de
int8_t
être untypedef
pourchar
.Comme l'a dit, le standard C99 (Section 6.2.5/4 cité ci-dessus) définit 5 standard des entiers signés types (
char
n'est pas l'un d'eux) et permet des implémentations pour ajouter leur onw qui sont visés en tant que non-standard des entiers signés types. La norme C++ renforce cette définition dans la Section 3.9.1/2:Plus tard, dans le même article, à l'alinéa 7 dit:
Par conséquent,
char
est un type entier, maischar
est ni un entier signé de type ni d'un type entier non signé et de l'Article 18.4.1 (cité ci-dessus) dit queint8_t
, lorsqu'il est présent, est untypedef
pour un entier signé de type.Ce qui pourrait être déroutant, c'est que, selon la mise en œuvre,
char
peut prendre les mêmes valeurs que unsigned char
. En particulier,char
pourrait avoir un signe, mais ce n'est toujours passigned char
. C'est explicitement dit dans la Section 3.9.1/1:Cela implique également que
char
est pas un entier signé de type, tels que définis par l'article 3.9.1/2.3. J'avoue que mon interprétation et, plus précisément, la phrase "
char
est ni un entier signé de type ni unsigned integer" est un peu controversé.À la force de mon cas, je voudrais ajouter que Stephan T. Lavavej dit la même chose ici et Johannes Schaub - litb également utilisé la même phrase dans un commentaire sur cette post.
int8_t != signed char
pour les deux raisons suivantes: 1)int8_t
pourrait être unchar
(un type distinct différente designed char
). 2) Même siint8_t
était une extension de type entier, il serait un type entier, voir [de base.fondamentaux]/2+7. Et [conv.bal]/1 nous dit, il pourrait être promu àint
ouunsigned int
(commeint
doit être >=char
>= 8 bits). Voir aussi la réponse de Daniel.operator<<
que peut prendre l'appel. Merci de souligner ce point. Je vais corriger le post. Cependant, comme je le comprends,int8_t
ne peut pas être unchar
. Je vais ajouter plus d'informations sur ce point. S'il vous plaît, laissez-moi savoir ce que vous en pensez.char
n'est pas tout à fait clair pour moi. C'est un intégrale mais ni un connecté, ni unsigned integer. Pourrait-il être un typedef pour une extension de type entier?int8_t
àint
est certainement possible (int
>= 16 bits); de même pouruint8_t
etunsigned int
. Par conséquent, si elle doit être converti, il va être promu à unint
et la sortie sera65
(ou quel que soit le nombre) plutôt que deA
. En Plus je ne suis pas encore sûr de savoir sitypedef extended_int char; typedef extended_int int8_t;
est légal ou pas.char
est un type standard et standard et étendu les types doivent être différents.typedef extended_int int8_t
est légal. Je crois, mais je ne suis pas sûr (comme expliqué dans mon post), queuint8_t
peut être promu àsigned char
et, par conséquent, " A " sera imprimé (pas65
).uint8_t
ne peut pas être promu poursigned char
, il ne peut être promu soitint
ouunsigned int
4.5[conv.bal]/1; mais comme C spécifieint
est >= 16 bits, il ne peut être promu àint
. Il peut être convertis poursigned char
, cependant, mais la promotion ne sera préféré au cours de la résolution de surcharge [plus.ics.rang].uint_8
n'est passigned char
, alors il peut être promu àint
, converti àsigned char
et la promotion est préférable lors de la résolution de surcharge. Par conséquent,65
sera imprimé. Je vais mettre à jour bientôt. Concernant le standard et étendue types différents: il est implicite par [conv.classement]/1. Plus précisément, il est dit, "Le rang d'une norme de type entier sera plus grande que le rang de la prolongation de type entier avec la même taille." Si une norme de type integer est un typedef pour une extension de type entier, alors ils ont la même taille et de même rang. Merci pour la belle discussion.typedef extended_type char;
contredit le Std.L'ébauche de l'exemplaire que j'ai, N3376, précise dans [cstdint.syn] § 18.4.1 que l'int types sont généralement typedefs.
Puisque la seule condition est qu'il doit être de 8 bits, puis typedef pour un char est acceptable.
char
/signed char
/unsigned char
sont de trois types différents, et unchar
n'est pas toujours 8 bits. sur la plupart des plate-forme, ils sont tous les 8-bits, mais std::ostream défini char version de>>
pour des comportements commescanf("%c", ...)
.int8_t
.CHAR_BIT
dans <climits> définit le nombre de bits dans unchar
. Bien que je n'ai pas vu de plate-forme avec CHAR_BIT valeur autre que 8.CHAR_BIT
est supérieur à 8, puisint8_t
n'existe pas sur la plate-forme. La Norme ne permet pasCHAR_BIT
être inférieur à 8.