Qu'est-ce que la norme C ++ indique la taille du type long et int?

696

Je recherche des informations détaillées sur la taille des types de base C ++. Je sais que cela dépend de l'architecture (16 bits, 32 bits, 64 bits) et du compilateur.

Mais existe-t-il des normes pour C ++?

J'utilise Visual Studio 2008 sur une architecture 32 bits. Voici ce que j'obtiens:

char  : 1 byte
short : 2 bytes
int   : 4 bytes
long  : 4 bytes
float : 4 bytes
double: 8 bytes

J'ai essayé de trouver, sans beaucoup de succès, des informations fiables indiquant les dimensions de char, short, int, long, double, float(et d' autres types , je ne pense pas que des) sous différentes architectures et compilateurs.

Jérôme
la source
18
@thyrgle ce n'est pas par choix ... il y a tellement d'architectures à prendre en charge qu'il doit être flexible.
Krakkos
4
Pourquoi ne suppriment-ils pas tous les types vagues et les normalisent-ils tous aux types de longueur de bits définis, par exemple int32_t, uint32_t, int64_t etc.
developerbmw
5
@thyrgle Il est en fait assez difficile de standardiser quelque chose comme ça. Contrairement à Java, où ces choses sont constantes en raison du fonctionnement de la JVM, C / C ++ doit essentiellement s'en tenir au système sur lequel elles sont exécutées sans aucune couche d'abstraction de fantaisie (du moins pas autant qu'avec Java). entre. Si la taille de l'int est si importante que l'on peut utiliser int16_t, int32_tet int64_t(besoin de l' iostreaminclure pour cela si je me souviens bien). Ce qui est bien à ce sujet, c'est que int64_t ne devrait pas avoir de problèmes sur un système 32 bits (cela aura un impact sur les performances).
rbaleksandar
5
@rbaleksandar Ils sont en fait définis dans <cstdint>, non <iostream>.
Justin Time - Rétablir Monica le

Réponses:

685

La norme C ++ ne spécifie pas la taille des types intégraux en octets, mais elle spécifie les plages minimales qu'ils doivent pouvoir contenir. Vous pouvez déduire la taille minimale en bits de la plage requise. Vous pouvez en déduire la taille minimale en octets et la valeur de la CHAR_BITmacro qui définit le nombre de bits dans un octet . Dans toutes les plates-formes, sauf les plus obscures, il s'agit de 8, et il ne peut pas être inférieur à 8. C'est parce qu'il doit être suffisamment grand pour contenir "les unités de code à huit bits de la forme de codage Unicode UTF-8".

Une contrainte supplémentaire charest que sa taille est toujours de 1 octet, ou CHAR_BITbits (d'où le nom). Ceci est indiqué explicitement dans la norme.

La norme C est une référence normative pour la norme C ++, donc même si elle n'énonce pas ces exigences explicitement, C ++ requiert les plages minimales requises par la norme C (page 22), qui sont les mêmes que celles des plages de types de données sur MSDN :

  1. signed char: -127 à 127 (notez, pas -128 à 127; ceci accepte les plates-formes de complément à 1 et signe-amplitude)
  2. unsigned char: 0 à 255
  3. "plain" char: même plage que signed charor unsigned char, définie par l'implémentation
  4. signed short: -32767 à 32767
  5. unsigned short: 0 à 65535
  6. signed int: -32767 à 32767
  7. unsigned int: 0 à 65535
  8. signed long: -2147483647 à 2147483647
  9. unsigned long: 0 à 4294967295
  10. signed long long: -9223372036854775807 à 9223372036854775807
  11. unsigned long long: 0 à 18446744073709551615

Une implémentation C ++ (ou C) peut définir la taille d'un type en octets sizeof(type)à n'importe quelle valeur, tant que

  1. l'expression est sizeof(type) * CHAR_BITévaluée à un nombre de bits suffisamment élevé pour contenir les plages requises, et
  2. la commande de type est toujours valide (par exemple sizeof(int) <= sizeof(long)).

Dans l'ensemble, nous avons la garantie que:

  • char,, signed charet unsigned charsont au moins 8 bits
  • signed short, unsigned short, signed int, Et unsigned intsont au moins 16 bits
  • signed longet unsigned longsont au moins 32 bits
  • signed long longet unsigned long longsont au moins 64 bits

Aucune garantie n'est faite quant à la taille floatou à l' doubleexception qui doublefournit au moins autant de précision que float.

Les plages spécifiques à l'implémentation peuvent être trouvées dans l'en- <limits.h>tête en C, ou <climits>en C ++ (ou encore mieux, basées std::numeric_limitssur un modèle dans l'en- <limits>tête).

Par exemple, voici comment vous trouverez la portée maximale pour int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
Alex B
la source
49
Au contraire, la norme C ++ utilise le mot octet pour signifier "1 char", et non la signification habituelle.
Ben Voigt
4
@Programmer Lisez la réponse (note 1 point entre parenthèses), ou le libellé de la norme réelle (lié dans la réponse). La norme C prend en charge les architectures du complément à 1, qui ont une représentation différente du complément à 2 le plus répandu. Les plages minimales garanties différeront presque toujours des plages réelles fournies par une implémentation.
Alex B
9
@Alex B, vous n'avez rien mentionné de double dans votre réponse. Pouvez-vous mettre à jour votre réponse pour les variables à virgule flottante?
Cool_Coder
3
@Cool_Coder: La virgule flottante est une marmite supplémentaire de poisson, doublant facilement la taille des poteaux.
Deduplicator
3
@Mooing Duck: "toutes les versions de C ++ nécessitaient 256 valeurs distinctes [pour les types de caractères signés]" Non, ce n'était pas vrai jusqu'à ce qu'il soit corrigé dans les spécifications C ++ les plus récentes. Les anciennes spécifications autorisaient les types de caractères signés à avoir des modèles de bits qui ne correspondent pas à un nombre, de sorte qu'ils n'avaient pas besoin de 256 valeurs distinctes. "Pour les types de caractères non signés, tous les modèles binaires possibles de la représentation de valeur représentent des nombres. Ces exigences ne s'appliquent pas aux autres types."
Adrian McCarthy
241

Pour les systèmes 32 bits, la norme «de facto» est ILP32 - c'est-à-dire int, longet le pointeur sont tous des quantités 32 bits.

Pour les systèmes 64 bits, la norme Unix principale de facto est LP64 - longet le pointeur est 64 bits (mais int32 bits). La norme Windows 64 bits est LLP64 - long longet pointeur sont 64 bits (mais longet intsont tous les deux 32 bits).

À un moment donné, certains systèmes Unix utilisaient une organisation ILP64.

Aucune de ces normes de facto n'est légiférée par la norme C (ISO / IEC 9899: 1999), mais toutes y sont autorisées.

Et, par définition, sizeof(char)est 1, malgré le test dans le script de configuration Perl.

Notez qu'il y avait des machines (Crays) où CHAR_BITétait beaucoup plus grand que 8. Cela signifiait, IIRC, qui sizeof(int)était également 1, car les deux charet intétaient 32 bits.

Jonathan Leffler
la source
73
+1 pour indiquer comment les choses sont réellement dans les cas qui comptent le plus, plutôt que comment les choses sont en théorie. Si vous voulez utiliser 32 bits int, si vous voulez utiliser 64 bits longtemps. Si vous voulez utiliser nativement size_t. Évitez les "simples" car ils varient. Cela devrait fonctionner pour la plupart des applications.
Eloff
37
+1 pour la réponse. @Eloff: au contraire ... si vous voulez une utilisation en 32 bits [u]int32_tou similaire, si vous voulez une utilisation en 64 bits [u]int64_t... si vous n'avez pas d'en-tête pour eux, téléchargez-en ou créez-en un, de préférence avec la sélection du temps de compilation de ces types ou assertions statiques pour vérifier la taille. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Si les tailles précises ne sont pas si importantes et que vous vous souciez seulement qu'elles soient au moins aussi grandes, alors votre conseil vaut pour les plates-formes PC / serveurs modernes et courantes.
Tony Delroy
8
Notez que ce ne sont pas seulement les vieilles machines à crayons qui ont CHAR_BIT> 8. Par exemple, les DSP ont souvent CHAR_BIT de 16 ou 32. (voir par exemple ceux-ci )
nos
2
@nos: Merci pour le lien. Il est très utile d'avoir identifié des systèmes modernes et actuels pour les cas excentriques. Par curiosité, quel est le code défini sur ces machines? Si le jeu de codes est UTF-16, alors 0xFFFF n'est pas un caractère valide, et si le jeu de codes est un jeu de codes ISO 8859-x, alors encore 0xFFFF n'est pas un caractère valide (les codes de caractères de 0x00 à 0xFF sont valides). Je ne suis pas encore convaincu qu'il y ait un problème de détection d'EOF, mais il y a certainement place à la prudence, et probablement à l'écriture et à l'utilisation d'une fonction int get_char(FILE *fp, char *c)qui renvoie EOF ou 0 et définit *c.
Jonathan Leffler
2
@joelw: C11 requiert que, étant donné uint32_t x=1,y=2;la valeur de x-ydoit être 4294967295 sur les plates-formes où "int" est de 32 bits ou moins, et -1 sur les plates-formes où "int" est de 33 bits ou plus. En outre, il x*ydoit être évalué en utilisant l'arithmétique modulaire pour toutes les valeurs de x et y si "int" est de 32 bits ou plus petit, et l'arithmétique conventionnelle si 65 bits ou plus, mais n'impose aucune exigence sur ce qui peut arriver avec de grandes valeurs de x et y si "int" est de 33 à 64 bits.
supercat
88

En pratique, il n'y a rien de tel. Souvent, vous pouvez vous attendre std::size_tà représenter la taille entière native non signée sur l'architecture actuelle. c'est-à-dire 16 bits, 32 bits ou 64 bits mais ce n'est pas toujours le cas comme indiqué dans les commentaires de cette réponse.

En ce qui concerne tous les autres types intégrés, cela dépend vraiment du compilateur. Voici deux extraits tirés du brouillon de travail actuel de la dernière norme C ++:

Il existe cinq types d'entiers signés standard: char signé, int court, int, long int et long long int. Dans cette liste, chaque type fournit au moins autant de stockage que ceux qui le précèdent dans la liste.

Pour chacun des types d'entiers signés standard, il existe un type d'entier standard non signé correspondant (mais différent): char non signé, entier court non signé, entier non signé, entier long non signé et entier long long non signé, chacun occupant la même quantité de stockage et a les mêmes exigences d'alignement.

Si vous le souhaitez, vous pouvez statiquement (au moment de la compilation) affirmer la taille de ces types fondamentaux. Il alertera les gens à penser à porter votre code si la taille des hypothèses change.

John Leidegren
la source
7
bon poste. une autre chose qui est requise est la taille minimale des bits suivante (documentée en c89 / c99 avec limits.h et reprise par c ++): char> = 8, short et int> = 16, long> = 32.
Johannes Schaub - litb
1
De plus, sur une plate-forme AVR 8 bits, size_t ne sera pas 8 bits, mais 16, car les tailles de pointeur et d'int sont 16 bits. La taille des données natives du processeur n'est donc pas liée à size_t.
Robotbugs
80

Il y a du standard.

La norme C90 exige que

sizeof(short) <= sizeof(int) <= sizeof(long)

La norme C99 exige que

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

Voici les spécifications C99 . La page 22 détaille les tailles de différents types intégraux.

Voici les tailles de type int (bits) pour les plates-formes Windows:

Type           C99 Minimum     Windows 32bit
char           8               8
short          16              16
int            16              32
long           32              32
long long      64              64

Si vous êtes concerné par la portabilité, ou si vous voulez que le nom du type reflète la taille, vous pouvez regarder l'en-tête <inttypes.h>, où les macros suivantes sont disponibles:

int8_t
int16_t
int32_t
int64_t

int8_test garanti à 8 bits, et int16_test garanti à 16 bits, etc.

yinyueyouge
la source
8
Petite piqûre: où dit le standard sizeof(long) < sizeof(long long)par opposition au symétrique sizeof(long) <= sizeof(long long)?
Jonathan Leffler
2
@JonathonLeffler - voir C99 5.2.4.2.1 - Tailles des types entiers. minsizeof (int) == 16 bits, minsizeof (long) == 32 bits, minsizeof (long long) == 64 bits. Je pense donc que vous avez raison sur le <= car aucun maxsizeof (type) n'est spécifié.
Jesse Chisholm
De même, sizeof (float) <= sizeof (double) <= sizeof (long double). Selon C99 7.12 paragraphe 2.
Jesse Chisholm
38

Si vous avez besoin de types de taille fixe, utilisez des types comme uint32_t (entier non signé 32 bits) défini dans stdint.h . Ils sont spécifiés en C99 .

Ben
la source
10
Ils sont spécifiés mais pas obligatoires.
dreamlax
2
@dreamlax Quelles plateformes ne l'incluent pas?
Levi Morrison
3
@LeviMorrison: Toute plate-forme qui ne les a pas sous la forme requise. Une plateforme qui l'a CHAR_BIT == 16, par exemple, n'aura pas int8_t. Toute plate - forme ne pas utiliser le complément de deux n'aura aucune d'entre eux (comme complément à deux est requis par la norme).
DevSolar
36

Mise à jour: C ++ 11 a officiellement introduit les types de TR1 dans la norme:

  • long long int
  • non signé long long int

Et les types "dimensionnés" de <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (et les homologues non signés).

De plus, vous obtenez:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Plus les homologues non signés.

Ces types représentent les plus petits types entiers avec au moins le nombre de bits spécifié. De même, il existe les types entiers "les plus rapides" avec au moins le nombre de bits spécifié:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Plus les versions non signées.

Ce qui signifie "rapide", s'il en est, dépend de la mise en œuvre. Il ne doit pas non plus être le plus rapide à toutes fins.

Brian Neal
la source
Cela fait maintenant partie de la norme C ++ 11.
Jaan
2
«rapide» signifie simplement adapté à l'architecture matérielle. Si les registres sont 16 bits, alors int_fast8_t est une valeur 16 bits. Si les registres sont 32 bits, int_fast8_t et int_fast16_t sont tous les deux des valeurs 32 bits. etc. Voir C99 section 7.18.1.3 paragraphe 2.
Jesse Chisholm
19

La norme C ++ le dit comme ceci:

3.9.1, §2:

Il existe cinq types d'entiers signés: "char signé", "short int", "int", "long int" et "long long int". Dans cette liste, chaque type fournit au moins autant de stockage que ceux qui le précèdent dans la liste. Les entiers simples ont la taille naturelle suggérée par l'architecture de l'environnement d'exécution (44); les autres types d'entiers signés sont fournis pour répondre à des besoins particuliers.

(44) c'est-à-dire suffisamment grand pour contenir toute valeur dans la plage de INT_MIN et INT_MAX, comme défini dans l'en-tête <climits> .

La conclusion: cela dépend de l'architecture sur laquelle vous travaillez. Toute autre hypothèse est fausse.

Jérôme Radix
la source
12

Non, il n'y a pas de norme pour les tailles de caractères. La norme requiert uniquement que:

sizeof(short int) <= sizeof(int) <= sizeof(long int)

La meilleure chose que vous puissiez faire si vous voulez des variables de tailles fixes est d'utiliser des macros comme celle-ci:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

Ensuite, vous pouvez utiliser WORD pour définir vos variables. Ce n'est pas que j'aime ça mais c'est le moyen le plus portable .

Emiliano
la source
4
Le problème est que WORD se propage dans le programme dans des zones qui ne dépendent pas vraiment d'une taille fixe (regardez du code Windows). Comme je l'ai découvert en passant d'un système 16 bits à un système 32 bits, vous vous retrouvez avec le même problème que WORD était censé résoudre.
lilburne
@liburne Bien sûr, vous ne devez utiliser WORD que lorsque vous avez besoin d'une variable de taille fixe, comme lorsque vous lisez / écrivez depuis / vers un fichier. Si un morceau de code ne dépend pas vraiment d'une taille fixe, vous devez utiliser des variables "int" normales.
Emiliano
3
La meilleure chose que vous puissiez faire pour obtenir des tailles portables devrait être#include <boost/cstdint.hpp>
kizzx2
11

Nous sommes autorisés à définir un synonyme pour le type afin que nous puissions créer notre propre "standard".

Sur une machine dans laquelle sizeof (int) == 4, on peut définir:

typedef int int32;

int32 i;
int32 j;
...

Ainsi, lorsque nous transférons le code sur une machine différente où la taille de long int est en fait de 4, nous pouvons simplement redéfinir la seule occurrence de int.

typedef long int int32;

int32 i;
int32 j;
...
milan-j
la source
1
Ce n'est pas nécessaire compte tenu de l'en-tête standard <stdint.h>(C99 et versions ultérieures, et quel que soit le standard C ++ adopté la version C99 de la bibliothèque C).
Keith Thompson
8

Pour les nombres à virgule flottante, il existe une norme (IEEE754) : les flottants sont 32 bits et les doubles sont 64. Il s'agit d'une norme matérielle, pas d'une norme C ++, de sorte que les compilateurs pourraient théoriquement définir flottant et doubler à une autre taille, mais en pratique, je '' Je n'ai jamais vu une architecture utilisant quelque chose de différent.

Crashworks
la source
2
Cependant, la conformité avec IEEE 754 (alias IEC 559) est facultative dans C ++ (probablement C aussi, mais je ne suis pas sûr). Voir std :: numeric_limits :: is_iec559.
Drew Hall
1
Ensuite, vous n'avez pas vu le compilateur de TI pour les DSP TMS320C28xx, où doublea la même taille que float(et intla même que char, les deux sont 16 bits). Mais ils ont un 64 bits long double.
starblue
7

Il existe une norme et elle est précisée dans les différents documents de normes (ISO, ANSI et ainsi de suite).

Wikipedia a une grande page expliquant les différents types et le maximum qu'ils peuvent stocker: Entier en informatique.

Cependant, même avec un compilateur C ++ standard, vous pouvez le découvrir relativement facilement en utilisant l'extrait de code suivant:

#include <iostream>
#include <limits>


int main() {
    // Change the template parameter to the various different types.
    std::cout << std::numeric_limits<int>::max() << std::endl;
}

La documentation de std :: numeric_limits peut être trouvée sur Roguewave . Il comprend une pléthore d'autres commandes que vous pouvez appeler pour connaître les différentes limites. Cela peut être utilisé avec n'importe quel type arbitraire qui transmet la taille, par exemple std :: streamsize.

La réponse de John contient la meilleure description, car celles-ci sont garanties de tenir. Quelle que soit la plateforme sur laquelle vous vous trouvez, il existe une autre bonne page qui explique plus en détail le nombre de bits que chaque type DOIT contenir: les types int , qui sont définis dans la norme.

J'espère que ça aide!

X-Istence
la source
7

Vous pouvez utiliser:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int, long intetc. Vous pourrez voir la taille du type de données que vous saisissez.

Population Xplosive
la source
7

Lorsqu'il s'agit de types intégrés pour différentes architectures et différents compilateurs, exécutez simplement le code suivant sur votre architecture avec votre compilateur pour voir ce qu'il génère. Ci-dessous montre ma sortie Ubuntu 13.04 (Raring Ringtail) 64 bits g ++ 4.7.3. Veuillez également noter ce qui a été répondu ci-dessous, c'est pourquoi la sortie est ordonnée en tant que telle:

"Il existe cinq types d'entiers signés standard: char signé, int court, int, long int et long long int. Dans cette liste, chaque type fournit au moins autant de stockage que ceux qui le précèdent dans la liste."

#include <iostream>

int main ( int argc, char * argv[] )
{
  std::cout<< "size of char: " << sizeof (char) << std::endl;
  std::cout<< "size of short: " << sizeof (short) << std::endl;
  std::cout<< "size of int: " << sizeof (int) << std::endl;
  std::cout<< "size of long: " << sizeof (long) << std::endl;
  std::cout<< "size of long long: " << sizeof (long long) << std::endl;

  std::cout<< "size of float: " << sizeof (float) << std::endl;
  std::cout<< "size of double: " << sizeof (double) << std::endl;

  std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}


size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
bjackfly
la source
sizeof(char)ne doit pas être inclus.
Ven
3

Comme mentionné, la taille doit refléter l'architecture actuelle. Vous pouvez faire un tour limits.hsi vous voulez voir comment votre compilateur actuel gère les choses.

John T
la source
Merci, mais j'aimerais connaître les tailles pour les architectures que je n'ai pas moi-même (comme 64 bits). Ce tutoriel ne parle que des architectures 32bits ...
Jérôme
2

Comme d'autres l'ont répondu, les "normes" laissent toutes la plupart des détails comme "implémentation définie" et indiquent seulement que le type "char" est au moins "char_bis" large, et que "char <= short <= int <= long < = long long "(float et double sont à peu près cohérents avec les normes IEEE à virgule flottante, et long double est généralement identique à double - mais peut être plus grand sur les implémentations plus actuelles).

Une partie des raisons pour ne pas avoir de valeurs très spécifiques et exactes est que des langages comme C / C ++ ont été conçus pour être portables sur un grand nombre de plates-formes matérielles - Y compris les systèmes informatiques dans lesquels la taille de mot "char" peut être de 4 bits ou 7 bits, ou même une valeur autre que les ordinateurs "8/16/32/64 bits" auxquels l'utilisateur moyen d'un ordinateur domestique est exposé. (La taille des mots signifie ici combien de bits de large le système fonctionne normalement - Encore une fois, ce n'est pas toujours 8 bits comme les utilisateurs d'ordinateurs personnels peuvent s'y attendre.)

Si vous avez vraiment besoin d'un objet (dans le sens d'une série de bits représentant une valeur intégrale) d'un nombre spécifique de bits, la plupart des compilateurs ont une méthode pour le spécifier; Mais ce n'est généralement pas portable, même entre des compilateurs fabriqués par la société ame mais pour différentes plates-formes. Certaines normes et pratiques (en particulier limits.h et similaires) sont suffisamment courantes pour que la plupart des compilateurs prennent en charge la détermination du type le mieux adapté pour une plage de valeurs spécifique, mais pas le nombre de bits utilisés. (Autrement dit, si vous savez que vous devez conserver des valeurs comprises entre 0 et 127, vous pouvez déterminer que votre compilateur prend en charge un type "int8" de 8 bits qui sera suffisamment grand pour contenir la plage complète souhaitée, mais pas quelque chose comme un type "int7" qui correspondrait exactement à 7 bits.)

Remarque: De nombreux packages source Un * x utilisaient le script "./configure" qui sonderait les capacités du compilateur / système et produirait un Makefile approprié et config.h. Vous pouvez examiner certains de ces scripts pour voir comment ils fonctionnent et comment ils sondent les capacités du comilateur / système et suivre leur exemple.

CM
la source
1

Si vous êtes intéressé par une solution C ++ pure, j'ai utilisé des modèles et uniquement du code standard C ++ pour définir des types au moment de la compilation en fonction de leur taille en bits. Cela rend la solution portable sur les compilateurs.

L'idée derrière est très simple: créer une liste contenant les types char, int, short, long, long long (versions signées et non signées) et analyser la liste et en utilisant le modèle numeric_limits sélectionner le type avec la taille donnée.

En incluant cet en-tête, vous avez obtenu 8 types stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Si un type ne peut pas être représenté, il sera évalué en stdtype :: null_type également déclaré dans cet en-tête.

LE CODE CI-DESSOUS EST DONNÉ SANS GARANTIE, S'IL VOUS PLAÎT DOUBLE LE VERIFIER.
JE SUIS NOUVEAU CHEZ METAPROGRAMMING TOO, N'HÉSITEZ PAS À MODIFIER ET À CORRIGER CE CODE.
Testé avec DevC ++ (donc une version gcc autour de 3.5)

#include <limits>

namespace stdtype
{
    using namespace std;


    /*
     * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
     * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS 
     * DECLARED/USED.
     *
     * PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
     */
    class null_type{};

    /*
     *  Template for creating lists of types
     *
     *  T is type to hold
     *  S is the next type_list<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> struct find_type
    {   
        private:
            //Handy name for the type at the head of the list
            typedef typename list::value cur_type;

            //Number of bits of the type at the head
            //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
            enum {cur_type_bits = numeric_limits<cur_type>::digits};

        public:
            //Select the type at the head if b == cur_type_bits else
            //select_type call find_type with list::next
            typedef  typename select_type<list, b, cur_type_bits>::type type;
    };

    /*
     * This is the specialization for empty list, return the null_type
     * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
     * (ie search for type with 17 bits on common archs)
     */
    template <int b> struct find_type<null_type, b>
    {   
        typedef null_type type;

    };


    /*
     * Primary template for selecting the type at the head of the list if
     * it matches the requested bits (b == ctl)
     *
     * If b == ctl the partial specified templated is evaluated so here we have
     * b != ctl. We call find_type on the next element of the list
     */
    template <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::type type; 
    };

    /*
     * This partial specified templated is used to select top type of a list
     * it is called by find_type with the list of value (consumed at each call)
     * the bits requested (b) and the current type (top type) length in bits
     *
     * We specialice the b == ctl case
     */
    template <typename list, int b> struct select_type<list, b, b>
    {
            typedef typename list::value type;
    };


    /*
     * These are the types list, to avoid possible ambiguity (some weird archs)
     * we kept signed and unsigned separated
     */

    #define UNSIGNED_TYPES type_list<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * These are acutally typedef used in programs.
     * 
     * Nomenclature is [u]intN where u if present means unsigned, N is the 
     * number of bits in the integer
     *
     * find_type is used simply by giving first a type_list then the number of 
     * bits to search for.
     *
     * NB. Each type in the type list must had specified the template 
     * numeric_limits as it is used to compute the type len in (binary) digit.
     */
    typedef find_type<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}
user781847
la source
0
unsigned char bits = sizeof(X) << 3;

Xest un char, int, longetc .. vous donnera la taille des Xen bits.

user3154672
la source
1
un caractère n'est pas toujours 8 bits, donc votre expression ne fonctionnera pas sur les architectures avec un caractère non 8 bits . sizeof(type)*CHAR_BITDétient uniquement
phuclv
Même s'ils CHAR_BITétaient garantis à 8 bits, il << 3s'agit simplement d'un moyen obscur pour écrire * 8ou * CHAR_BIT.
Keith Thompson
0

De Alex B La norme C ++ ne spécifie pas la taille des types intégraux en octets, mais elle spécifie les plages minimales qu'ils doivent pouvoir contenir. Vous pouvez déduire la taille minimale en bits de la plage requise. Vous pouvez en déduire la taille minimale en octets et la valeur de la macro CHAR_BIT qui définit le nombre de bits dans un octet (dans toutes les plates-formes sauf les plus obscures, c'est 8, et il ne peut pas être inférieur à 8).

Une contrainte supplémentaire pour char est que sa taille est toujours de 1 octet, ou CHAR_BIT bits (d'où le nom).

Les plages minimales requises par la norme (page 22) sont:

et plages de types de données sur MSDN:

caractère signé: -127 à 127 (remarque, pas -128 à 127; cela accepte les plates-formes complémentaires de 1) caractère non signé: 0 à 255 caractère "ordinaire": -127 à 127 ou 0 à 255 (dépend de la signature par défaut du caractère) signé court: -32767 à 32767 non signé court: 0 à 65535 signé int: -32767 à 32767 non signé int: 0 à 65535 signé long: -2147483647 à 2147483647 non signé long: 0 à 4294967295 signé long long: -9223372036854775807 à 9223372036854775807 non signé 0 à 18446744073709551615 Une implémentation C ++ (ou C) peut définir la taille d'un type en octets sizeof (type) à n'importe quelle valeur, tant que

l'expression sizeof (type) * CHAR_BIT évalue le nombre de bits suffisamment pour contenir les plages requises et l'ordre de type est toujours valide (par exemple sizeof (int) <= sizeof (long)). Les plages spécifiques à l'implémentation peuvent être trouvées dans l'en-tête en C, ou en C ++ (ou encore mieux, les modèles std :: numeric_limits dans l'en-tête).

Par exemple, voici comment vous trouverez la plage maximale pour int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

C'est exact, cependant, vous aviez également raison de dire que: char: 1 octet court: 2 octets int: 4 octets long: 4 octets float: 4 octets double: 8 octets

Parce que les architectures 32 bits sont toujours par défaut et les plus utilisées, et elles ont conservé ces tailles standard depuis les jours pré-32 bits où la mémoire était moins disponible, et pour la compatibilité et la normalisation en amont, elle est restée la même. Même les systèmes 64 bits ont tendance à les utiliser et ont des extensions / modifications. Veuillez vous y référer pour plus d'informations:

http://en.cppreference.com/w/cpp/language/types

JCoder
la source
0

Je remarque que toutes les autres réponses ici se sont concentrées presque exclusivement sur les types intégraux, tandis que le questionneur a également posé des questions sur les virgules flottantes.

Je ne pense pas que la norme C ++ l'exige, mais les compilateurs pour les plates-formes les plus courantes de nos jours suivent généralement la norme IEEE754 pour leurs nombres à virgule flottante. Cette norme spécifie quatre types de virgule flottante binaire (ainsi que certains formats BCD, dont je n'ai jamais vu la prise en charge dans les compilateurs C ++):

  • Demi-précision (binaire16) - Signification 11 bits, plage d'exposants -14 à 15
  • Simple précision (binaire32) - Signification 24 bits, plage d'exposants -126 à 127
  • Double précision (binaire64) - signification 53 bits, plage d'exposants -1022 à 1023
  • Quadruple précision (binaire128) - Signification 113 bits, plage d'exposants -16382 à 16383

Comment cette mappe sur les types C ++, alors? Généralement, il floatutilise une seule précision; ainsi sizeof(float) = 4. doubleUtilise ensuite la double précision (je crois que c'est la source du nom double), et long doublepeut être double ou quadruple précision (c'est quadruple sur mon système, mais sur les systèmes 32 bits, cela peut être double). Je ne connais aucun compilateur offrant des virgules flottantes de demi-précision.

En résumé, c'est l'habituel:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 ou 16
celticminstrel
la source
C'est drôle que j'arrive à cette question dans le cadre de la question de savoir pourquoi Jeff utilise plus d'octets que nécessaire.
Aniruddha Varma
-2

Vous pouvez utiliser des variables fournies par des bibliothèques telles que OpenGL , Qt , etc.

Par exemple, Qt fournit qint8 (garanti 8 bits sur toutes les plates-formes prises en charge par Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.

Lawand
la source
1
Ne répond pas à la question
EvilTeach
-8

Sur une machine 64 bits:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8
user2826084
la source
2
Sur certaines machines 64 bits, intc'est 8 octets, mais l'autre n'est pas garanti. Il n'y a rien qui dit que cela charne devrait être que de 8 bits. Il est autorisé à l'avoir sizeof(void*)==4même s'il s'agit de 64 bits.
skyking
-10

Il existe quatre types d'entiers basés sur la taille:

  • entier court: 2 octets
  • entier long: 4 octets
  • entier long long: 8 octets
  • entier: dépend du compilateur (16 bits, 32 bits ou 64 bits)
branlant
la source
11
Faux, ils dépendent tous de l'architecture, avec les plages minimales décrites dans l'une des autres réponses. Rien n'empêche une implémentation d'avoirshort , intet longtous les entiers 32 bits.
Matteo Italia
Vous n'avez même pas utilisé les noms corrects pour les types. Les noms utilisent le mot-clé int, pas le mot "entier".
Keith Thompson