Recherche…


Char peut être non signé ou signé

La norme ne spécifie pas si char doit être signé ou non signé. Différents compilateurs l'implémentent différemment ou peuvent le modifier à l'aide d'un commutateur de ligne de commande.

Taille des types intégraux

Les types suivants sont définis comme types intégraux :

  • char
  • Types d'entiers signés
  • Types entiers non signés
  • char16_t et char32_t
  • bool
  • wchar_t

À l'exception de sizeof(char) / sizeof(signed char) / sizeof(unsigned char) , qui est divisé entre le § 3.9.1.1 [basic.fundamental / 1] et le § 5.3.3.1 [expr.sizeof], et sizeof(bool) , qui est entièrement défini par la mise en œuvre et n’a pas de taille minimale, les exigences de taille minimale de ces types sont données dans la section § 3.9.1 [élément fondamental] de la norme et doivent être détaillées ci-dessous.

Taille de char

Toutes les versions du C de la norme spécifient, au § 5.3.3.1, que sizeof rendements 1 pour unsigned char , signed char , et l' char (il est défini par l' implémentation si le char type est signed ou unsigned ).

C ++ 14

char est assez grand pour représenter 256 valeurs différentes, pour pouvoir stocker des unités de code UTF-8.

Taille des types d'entiers signés et non signés

La norme spécifie, au § 3.9.1.2, que dans la liste des types entiers signés standard , consistant en un caractère signed char , short int , un int , un long int et un long long int , chaque type fournira au moins autant de stockage que ceux précédents dans la liste. De plus, comme spécifié au § 3.9.1.3, chacun de ces types a un type d'entier non signé standard correspondant, un caractère non unsigned char , un unsigned short int , un unsigned int , un unsigned long int et unsigned long long int son type signé correspondant. En outre, comme spécifié au § 3.9.1.1, char a la même taille et les exigences d' alignement à la fois comme signed char et unsigned char .

C ++ 11

Avant C ++ 11, long long et unsigned long long ne faisaient pas officiellement partie du standard C ++. Cependant, après leur introduction à C, en C99, de nombreux compilateurs prenaient en charge long long entier signé étendu et ne signaient unsigned long long tant que type entier non signé étendu , avec les mêmes règles que les types C.

La norme garantit ainsi que:

1 == sizeof(char)  == sizeof(signed char) == sizeof(unsigned char)
  <= sizeof(short) == sizeof(unsigned short)
  <= sizeof(int)   == sizeof(unsigned int)
  <= sizeof(long)  == sizeof(unsigned long)
C ++ 11
 <= sizeof(long long) == sizeof(unsigned long long)

Les tailles minimales spécifiques pour chaque type ne sont pas données par la norme. Au lieu de cela, chaque type a une plage minimale de valeurs qu'il peut prendre en charge, à savoir, comme spécifié au § 3.9.1.3, hérité du standard C, au § 5.2.4.2.1. La taille minimale de chaque type peut être approximativement déduite de cette plage, en déterminant le nombre minimal de bits requis; notez que pour toute plate-forme donnée, la plage prise en charge réelle de tout type peut être supérieure au minimum. Notez que pour les types signés, les plages correspondent à son complément, pas au complément à deux plus communément utilisé; Cela permet à un plus large éventail de plates-formes de se conformer à la norme.

Type Portée minimale Bits minimum requis
signed char -127 à 127 (- (2 7 - 1) à (2 7 - 1)) 8
unsigned char 0 à 255 (0 à 2 8 - 1) 8
signed short -32767 à 32767 (- (février 15 à 1) à (15 à 1 février)) 16
unsigned short 0 à 65 535 (0 à 2 16 - 1) 16
signed int -32 767 à 32 767 (- (2 15 - 1) à (2 15 - 1)) 16
unsigned int 0 à 65 535 (0 à 2 16 - 1) 16
signed long -2 147 483 647 à 2 147 483 647 (- (2 31 - 1) à (2 31 - 1)) 32
unsigned long 0 à 4 294 967 295 (0 à 2 32 - 1) 32
C ++ 11
Type Portée minimale Bits minimum requis
signed long long -9 223 372 036 854 775 807 à 9 223 372 036 854 775 807 (- (2 63 - 1) à (2 63 - 1)) 64
unsigned long long 0 à 18,446,744,073,709,551,615 (0 à 2 64-1 ) 64

Chaque type pouvant être supérieur à la taille minimale requise, les types peuvent varier en taille entre les implémentations. L'exemple le plus notable de c'est avec les modèles de données 64 bits LP64 et LLP64, où les systèmes de LLP64 (tels que Windows 64 bits) ont 32 bits ints et long s et des systèmes LP64 (tels que Linux 64 bits) ont 32 bits int et 64 bits long s. De ce fait, les types d'entiers ne peuvent pas être supposés avoir une largeur fixe sur toutes les plates-formes.

C ++ 11

Si les entiers avec largeur fixe sont nécessaires, les types d'utilisation de la <cstdint> en- tête, mais notez que la norme rend facultative pour les implémentations de soutenir les types exacts de largeur int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t et uintptr_t .

C ++ 11

Taille de char16_t et char32_t

Les tailles de char16_t et char32_t sont définies par l'implémentation, comme spécifié au § 5.3.3.1, avec les stipulations du § 3.9.1.5:

  • char16_t est assez grand pour représenter n'importe quelle unité de code UTF-16 et a la même taille, la même signature et le même alignement que uint_least16_t ; il faut donc au moins 16 bits.

  • char32_t est assez grand pour représenter n'importe quelle unité de code UTF-32 et a la même taille, la même signature et le même alignement que uint_least32_t ; il faut donc au moins 32 bits.

Taille de bool

La taille de bool est définie par l'implémentation et peut ou non être 1 .

Taille de wchar_t

wchar_t , comme spécifié au § 3.9.1.5, est un type distinct, dont la plage de valeurs peut représenter chaque unité de code distincte du plus grand jeu de caractères étendu parmi les paramètres régionaux pris en charge. Il a la même taille, la même signature et le même alignement que l'un des autres types intégraux, connu sous le nom de son type sous-jacent . La taille de ce type est définie par la mise en œuvre, comme spécifié au § 5.3.3.1, et peut être, par exemple, d'au moins 8, 16 ou 32 bits; Si un système prend en charge Unicode, par exemple, wchar_t doit comporter au moins 32 bits (une exception à cette règle est Windows, où wchar_t correspond à 16 bits à des fins de compatibilité). Il est hérité de la norme C90, ISO 9899: 1990 § 4.1.5, avec seulement une reformulation mineure.

Selon l'implémentation, la taille de wchar_t est souvent, mais pas toujours, 8, 16 ou 32 bits. Les exemples les plus courants sont les suivants:

  • Dans les systèmes Unix et Unix, wchar_t est 32 bits et est généralement utilisé pour UTF-32.
  • Dans Windows, wchar_t est 16 bits et est utilisé pour UTF-16.
  • Sur un système qui ne prend en charge que 8 bits, wchar_t 8 bits.
C ++ 11

Si le support Unicode est souhaité, il est recommandé d'utiliser char pour UTF-8, char16_t pour UTF-16 ou char32_t pour UTF-32, au lieu d'utiliser wchar_t .


Modèles de données

Comme mentionné ci-dessus, les largeurs des types entiers peuvent différer entre les plates-formes. Les modèles les plus courants sont les suivants, avec des tailles spécifiées en bits:

Modèle int long aiguille
LP32 (2/4/4) 16 32 32
ILP32 (4/4/4) 32 32 32
LLP64 (4/4/8) 32 32 64
LP64 (4/8/8) 32 64 64

Sur ces modèles:

  • Windows 16 bits utilisé LP32.
  • Les systèmes nix 32 bits * (Unix, Linux, Mac OSX et autres systèmes d'exploitation de type Unix) et Windows utilisent ILP32.
  • Windows 64 bits utilise LLP64.
  • Les systèmes 64 bits * nix utilisent LP64.

Notez cependant que ces modèles ne sont pas spécifiquement mentionnés dans la norme elle-même.

Nombre de bits dans un octet

En C ++, un octet est l'espace occupé par un objet char . Le nombre de bits dans un octet est donné par CHAR_BIT , qui est défini dans les climits et doit être d'au moins 8. Alors que la plupart des systèmes modernes ont des octets de 8 bits, et POSIX exige que CHAR_BIT soit exactement 8, il existe certains systèmes où CHAR_BIT est supérieur à 8, c'est-à-dire qu'un seul octet peut être composé de 8, 16, 32 ou 64 bits.

Valeur numérique d'un pointeur

Le résultat du lancement d'un pointeur sur un entier à l'aide de reinterpret_cast est défini par l'implémentation, mais "... est destiné à être sans surprise pour ceux qui connaissent la structure d'adressage de la machine sous-jacente."

int x = 42;
int* p = &x;
long addr = reinterpret_cast<long>(p);
std::cout << addr << "\n"; // prints some numeric address,
                           // probably in the architecture's native address format

De même, le pointeur obtenu par conversion à partir d'un entier est également défini par l'implémentation.

La manière correcte de stocker un pointeur en tant uintptr_t consiste à utiliser les types uintptr_t ou intptr_t :

// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>

uintptr_t uip;
C ++ 11
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>

std::uintptr_t uip;

C ++ 11 fait référence à C99 pour la définition de uintptr_t (norme C99, 6.3.2.3):

un type d'entier non signé avec la propriété que tout pointeur valide à void peut être converti en ce type, puis reconverti en pointeur sur void , et le résultat sera égal au pointeur d'origine.

Alors que, pour la majorité des plates - formes modernes, vous pouvez supposer un espace d'adressage plat et que l' arithmétique sur uintptr_t équivaut à l' arithmétique sur char * , il est tout à fait possible pour une mise en œuvre pour réaliser une transformation lors de la coulée void * à uintptr_t tant la transformation peut être inversé lors du retour de uintptr_t pour void * .

Techniques

  • Sur les systèmes intptr_t XSI (X / Open System Interfaces), les types intptr_t et uintptr_t sont obligatoires, sinon ils sont facultatifs .

  • Au sens de la norme C, les fonctions ne sont pas des objets; le standard C ne garantit pas que uintptr_t puisse contenir un pointeur de fonction. Quoi qu’il en soit, la conformité POSIX (2.12.3) nécessite que:

    Tous les types de pointeurs de fonction doivent avoir la même représentation que le pointeur de type à annuler. La conversion d'un pointeur de fonction en void * ne modifie pas la représentation. Une valeur vide * résultant d'une telle conversion peut être reconvertie dans le type de pointeur de fonction d'origine, en utilisant une conversion explicite, sans perte d'informations.

  • C99 §7.18.1:

    Lorsque des noms typedef ne différant que par l'absence ou la présence de l'u initial sont définis, ils doivent indiquer les types signés et non signés correspondants, comme décrit au 6.2.5; une implémentation fournissant l'un de ces types correspondants fournira également l'autre.

    uintptr_t peut avoir un sens si vous voulez faire des choses sur les bits du pointeur que vous ne pouvez pas faire aussi intelligemment avec un entier signé.

Plages de types numériques

Les plages des types entiers sont définies par l'implémentation. L'en-tête <limits> fournit le modèle std::numeric_limits<T> qui fournit les valeurs minimales et maximales de tous les types fondamentaux. Les valeurs satisfont aux garanties fournies par le standard C via les en- <climits> et (> = C ++ 11) <cinttypes> .

  • std::numeric_limits<signed char>::min() est égal à SCHAR_MIN , qui est inférieur ou égal à -127.
  • std::numeric_limits<signed char>::max() est égal à SCHAR_MAX , qui est supérieur ou égal à 127.
  • std::numeric_limits<unsigned char>::max() est égal à UCHAR_MAX , qui est supérieur ou égal à 255.
  • std::numeric_limits<short>::min() est égal à SHRT_MIN , qui est inférieur ou égal à -32767.
  • std::numeric_limits<short>::max() est égal à SHRT_MAX , qui est supérieur ou égal à 32767.
  • std::numeric_limits<unsigned short>::max() est égal à USHRT_MAX , qui est supérieur ou égal à 65535.
  • std::numeric_limits<int>::min() est égal à INT_MIN , qui est inférieur ou égal à -32767.
  • std::numeric_limits<int>::max() est égal à INT_MAX , qui est supérieur ou égal à 32767.
  • std::numeric_limits<unsigned int>::max() est égal à UINT_MAX , qui est supérieur ou égal à 65535.
  • std::numeric_limits<long>::min() est égal à LONG_MIN , qui est inférieur ou égal à -2147483647.
  • std::numeric_limits<long>::max() est égal à LONG_MAX , qui est supérieur ou égal à 2147483647.
  • std::numeric_limits<unsigned long>::max() est égal à ULONG_MAX , qui est supérieur ou égal à 4294967295.
C ++ 11
  • std::numeric_limits<long long>::min() est égal à LLONG_MIN , qui est inférieur ou égal à -9223372036854775807.
  • std::numeric_limits<long long>::max() est égal à LLONG_MAX , qui est supérieur ou égal à 9223372036854775807.
  • std::numeric_limits<unsigned long long>::max() est égal à ULLONG_MAX , qui est supérieur ou égal à 18446744073709551615.

Pour les types à virgule flottante T , max() est la valeur finie maximale tandis que min() est la valeur normalisée positive minimale. Des membres supplémentaires sont fournis pour les types à virgule flottante, qui sont également définis par l'implémentation mais satisfont à certaines garanties fournies par le standard C via l'en-tête <cfloat> .

  • Le membre digits10 donne le nombre de chiffres décimaux de précision.
    • std::numeric_limits<float>::digits10 est égal à FLT_DIG , qui est au moins 6.
    • std::numeric_limits<double>::digits10 est égal à DBL_DIG , soit au moins 10.
    • std::numeric_limits<long double>::digits10 est égal à LDBL_DIG , soit au moins 10.
  • Le membre min_exponent10 est le minimum négatif E tel que 10 à la puissance E est normal.
    • std::numeric_limits<float>::min_exponent10 est égal à FLT_MIN_10_EXP , soit au maximum -37.
    • std::numeric_limits<double>::min_exponent10 est égal à DBL_MIN_10_EXP , soit au maximum -37. std::numeric_limits<long double>::min_exponent10 est égal à LDBL_MIN_10_EXP , soit au maximum -37.
  • Le membre max_exponent10 est le maximum E tel que 10 à la puissance E est fini.
    • std::numeric_limits<float>::max_exponent10 est égal à FLT_MIN_10_EXP , soit au moins 37.
    • std::numeric_limits<double>::max_exponent10 est égal à DBL_MIN_10_EXP , soit au moins 37.
    • std::numeric_limits<long double>::max_exponent10 est égal à LDBL_MIN_10_EXP , soit au moins 37.
  • Si le membre is_iec559 est vrai, le type est conforme à la norme IEC 559 / IEEE 754 et sa plage est donc déterminée par cette norme.

Représentation de la valeur des types à virgule flottante

Le standard exige que le long double fournisse au moins autant de précision que le double , ce qui fournit au moins autant de précision que le float ; et qu'un long double peut représenter n'importe quelle valeur qu'un double peut représenter, tandis qu'un double peut représenter n'importe quelle valeur qu'un float peut représenter. Les détails de la représentation sont cependant définis par la mise en œuvre.

Pour un type à virgule flottante T , std::numeric_limits<T>::radix spécifie la base utilisée par la représentation de T

Si std::numeric_limits<T>::is_iec559 est vrai, alors la représentation de T correspond à l'un des formats définis par la norme IEC 559 / IEEE 754.

Débordement lors de la conversion d'un entier en entier signé

Lorsqu'un entier signé ou non signé est converti en un type entier signé et que sa valeur n'est pas représentable dans le type de destination, la valeur produite est définie par l'implémentation. Exemple:

// Suppose that on this implementation, the range of signed char is -128 to +127 and
// the range of unsigned char is 0 to 255
int x = 12345;
signed char sc = x;   // sc has an implementation-defined value
unsigned char uc = x; // uc is initialized to 57 (i.e., 12345 modulo 256)

Type sous-jacent (et donc taille) d'un enum

Si le type sous-jacent n'est pas explicitement spécifié pour un type d'énumération non segmenté, il est déterminé d'une manière définie par l'implémentation.

enum E {
    RED,
    GREEN,
    BLUE,
};
using T = std::underlying_type<E>::type; // implementation-defined

Toutefois, la norme exige que le type sous-jacent d’une énumération ne soit pas supérieur à int moins que int et unsigned int ne puissent pas représenter toutes les valeurs de l’énumération. Par conséquent, dans le code ci-dessus, T pourrait être int , unsigned int ou short , mais pas long long , pour donner quelques exemples.

Notez qu'une énumération a la même taille (renvoyée par sizeof ) que son type sous-jacent.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow