La taille de C «int» est-elle de 2 octets ou 4 octets?

169

Une variable Integer en C occupe-t-elle 2 octets ou 4 octets? De quels facteurs cela dépend-il?

La plupart des manuels disent que les variables entières occupent 2 octets. Mais lorsque j'exécute un programme imprimant les adresses successives d'un tableau d'entiers, il montre la différence de 4.

Rajiv Prathap
la source
6
en.wikipedia.org/wiki/…
Evan Mulawski
1
intn'est qu'un des nombreux types d' entiers . Vous avez posé des questions sur la taille de "integer"; vous vouliez probablement poser des questions sur la taille de int.
Keith Thompson du
3
Et vous devriez trouver de meilleurs manuels. Un manuel qui dit an intvaut 2 octets (a) fait probablement référence à un ancien système, et (b) ne parvient pas à préciser que la taille variera d'un système à l'autre. Le meilleur livre sur C est "The C Programming Language" de Kernighan et Ritchie, bien qu'il suppose une certaine expérience en programmation. Voir aussi la question 18.10 de la FAQ comp.lang.c .
Keith Thompson du
2
Essayez #define int int64_tsur une plate-forme 64 bits, donc ni l'un ni l'autre. Utilisez simplement sizeof. ;-)
netcoder

Réponses:

183

Je sais que c'est égal à sizeof(int). La taille d'un intdépend vraiment du compilateur. À l'époque, lorsque les processeurs étaient 16 bits, un intétait de 2 octets. De nos jours, c'est le plus souvent 4 octets sur un système 32 bits ainsi que 64 bits.

Pourtant, l'utilisation sizeof(int)est le meilleur moyen d'obtenir la taille d'un entier pour le système spécifique sur lequel le programme est exécuté.

EDIT: Correction d'une déclaration erronée de int8 octets sur la plupart des systèmes 64 bits. Par exemple, il est de 4 octets sur GCC 64 bits.

yhyrcanus
la source
31
@RajivPrathap: Eh bien, cela dépend du compilateur, mais le compilateur décide si oui ou non il dépend également de la machine. :)
user541686
2
Si vous avez besoin de la taille du préprocesseur, vous pouvez vérifier les macros prédéfinies telles que INT_MAX. Si la valeur n'est pas celle attendue par votre code, la taille en octets de int est différente sur la combinaison compilateur / plateforme actuelle.
Walt Sellers
3
Non seulement dépendant de la machine, cela dépend également du système d'exploitation exécuté sur la machine. Par exemple, long dans Win64 est de 4 octets alors que long dans Linux64 est de 8 octets.
Cem Kalyoncu
9
faux. sur la plupart des systèmes 64 bits, int est toujours de 4 octets en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
phuclv
7
sizeof(int)peut être n'importe quelle valeur de 1. Il n'est pas nécessaire qu'un octet soit 8 bits et certaines machines n'ont pas d'unité adressable 8 bits (ce qui est fondamentalement la définition d'un octet dans la norme). La réponse n'est pas correcte sans plus d'informations.
trop honnête pour ce site
103

C'est l'un des points de C qui peut prêter à confusion au début, mais la norme C ne spécifie qu'une plage minimale pour les types entiers dont la prise en charge est garantie. intest garanti de pouvoir contenir -32767 à 32767, ce qui nécessite 16 bits. Dans ce cas int,, vaut 2 octets. Cependant, les implémentations sont libres d'aller au-delà de ce minimum, car vous verrez que de nombreux compilateurs modernes font du int32 bits (ce qui signifie également 4 octets de manière omniprésente).

La raison pour laquelle votre livre dit 2 octets est probablement parce qu'il est vieux. À une certaine époque, c'était la norme. En général, vous devez toujours utiliser l' sizeofopérateur si vous avez besoin de savoir combien d'octets il se trouve sur la plate-forme que vous utilisez.

Pour résoudre ce problème, C99 a ajouté de nouveaux types dans lesquels vous pouvez demander explicitement un certain entier de taille, par exemple int16_tou int32_t. Avant cela, il n'existait pas de moyen universel d'obtenir un entier d'une largeur spécifique (bien que la plupart des plates-formes fournissaient des types similaires sur une base par plate-forme).

Erreur fatale
la source
7
@nevanking: Sur une machine à complément à deux (qui est toutes les machines que je connais ...), oui. Mais, C ne garantit pas que ce soit le cas.
FatalError
@nevanking Je suis complètement nouveau en C, mais n'est-ce pas 32767 parce qu'autrement il utiliserait un autre bit | byte? Imaginez, je peux contenir 3 chiffres (0 ou 1), donc je peux passer de 000 à 111 (qui est décimal 7). 7 est juste avant un exposant de 2. Si je pouvais aller jusqu'à 8 (1000), alors je pourrais utiliser ces 4 chiffres jusqu'à 15! Par exemple, 32767 est juste avant un exposant de 2, épuisant tous les bits | octets dont il dispose.
RGS
3
@RSerrao Je ne suis pas non plus un expert en C, mais AFAIK pour les nombres positifs, c'est un de moins que le nombre négatif maximum. Donc -8 à 7, -256 à 255 et ainsi de suite. Les nombres négatifs ne doivent pas compter le zéro.
nevan king
1
"16 bits. Dans ce cas, int, vaut 2 octets" peut être erroné, si CHAR_BIT vaut 16, sizeof (int) peut être de 1 octet (ou char).
12431234123412341234123
6
@nevanking: uniquement si vous supposez une représentation complémentaire de 2 pour signé int. C ne fait pas cette hypothèse. Les systèmes de complément et de grandeur de signe de 1 ne peuvent pas représenter -32768en 16 bits; ils ont plutôt deux représentations pour zéro (positive et négative). C'est pourquoi la plage minimale pour un intest [-32767..32767].
John Bode
33

Il n'y a pas de réponse précise. Cela dépend de la plateforme. Il est défini par la mise en œuvre. Cela peut être 2, 4 ou autre chose.

L'idée derrière intétait qu'il était censé correspondre à la taille naturelle du "mot" sur la plate-forme donnée: 16 bits sur les plates-formes 16 bits, 32 bits sur les plates-formes 32 bits, 64 bits sur les plates-formes 64 bits, vous voyez l'idée. Cependant, à des fins de compatibilité descendante, certains compilateurs préfèrent s'en tenir au 32 bits intmême sur les plates-formes 64 bits.

Le temps de 2 octets intest révolu depuis longtemps (plates-formes 16 bits?) À moins que vous n'utilisiez une plate-forme intégrée avec une taille de mot de 16 bits. Vos manuels sont probablement très vieux.

Fourmi
la source
2
The idea behind int was that it was supposed to match the natural "word" size on the given platform- C'est ce que je cherchais. Une idée de la raison? Dans un monde libre, int pourrait occuper n'importe quel nombre d'octets consécutifs dans la mémoire, n'est-ce pas? 8, 16 peu importe
bholagabbar
19

La réponse à cette question dépend de la plate-forme que vous utilisez.
Mais quelle que soit la plate-forme, vous pouvez assumer de manière fiable les types suivants:

 [8-bit] signed char: -127 to 127
 [8-bit] unsigned char: 0 to 255
 [16-bit]signed short: -32767 to 32767
 [16-bit]unsigned short: 0 to 65535
 [32-bit]signed long: -2147483647 to 2147483647
 [32-bit]unsigned long: 0 to 4294967295
 [64-bit]signed long long: -9223372036854775807 to 9223372036854775807
 [64-bit]unsigned long long: 0 to 18446744073709551615
Priyank Arora
la source
3
Quelqu'un a modifié votre message pour "corriger" les plages, mais je ne suis pas sûr que votre modification reflète correctement votre intention. Il suppose une implémentation du complément à deux, ce qui sera vrai dans la plupart des cas, mais pas dans tous. Puisque votre réponse souligne spécifiquement la dépendance à l'implémentation, je pense que la modification est probablement erronée. Si vous acceptez, veillez à annuler la modification.
Cody Gray
1
@ k06a votre modification était incorrecte . Vous avez spécifiquement changé les plages d'origine en plages à 2 compléments - ce ne sont pas celles spécifiées dans la norme C.
Antti Haapala
@CodyGray cela a fluctué d'avant en arrière, ayant été conforme au complément de 1 au cours des 3 dernières années et OP ne disant rien, j'ai donc rétabli une modification qui l'a changé en complément de 2 avec des "plages de correction", car il dit "vous pouvez supposer de manière fiable" , ce qui n'est toujours pas tout à fait vrai.
Antti Haapala
13

Une variable Integer en C occupe-t-elle 2 octets ou 4 octets?

Cela dépend de la plate-forme que vous utilisez, ainsi que de la configuration de votre compilateur. La seule réponse qui fait autorité est d'utiliser l' sizeofopérateur pour voir la taille d'un entier dans votre situation spécifique.


De quels facteurs cela dépend-il?

La gamme pourrait être mieux considérée, plutôt que la taille . Les deux varient en pratique, bien qu'il soit beaucoup plus infaillible de choisir des types de variables par plage que par taille, comme nous le verrons. Il est également important de noter que la norme nous encourage à envisager de choisir nos types d'entiers en fonction de la plage plutôt que de la taille , mais pour l'instant ignorons la pratique standard , et laissons notre curiosité explorer sizeof, octets et CHAR_BIT, et représentation entière ... le terrier du lapin et le voir par nous-mêmes ...


sizeof, octets et CHAR_BIT

La déclaration suivante, tirée de la norme C (liée à ci-dessus), décrit cela avec des mots que je ne pense pas pouvoir être améliorés.

L' sizeofopérateur donne la taille (en octets) de son opérande, qui peut être une expression ou le nom entre parenthèses d'un type. La taille est déterminée à partir du type de l'opérande.

En supposant qu'une compréhension claire nous mènera à une discussion sur les octets . Il est communément admis qu'un octet est de huit bits, alors qu'en fait, CHAR_BITvous indique combien de bits il y a dans un octet . C'est juste une autre de ces nuances qui n'est pas prise en compte lorsque l'on parle des entiers communs à deux (ou quatre) octets .

Concluons les choses jusqu'à présent:

  • sizeof => taille en octets, et
  • CHAR_BIT => nombre de bits dans l'octet

Ainsi, selon votre système, sizeof (unsigned int)peut être n'importe quelle valeur supérieure à zéro (pas seulement 2 ou 4), comme si CHAR_BITétait 16, alors un seul octet (seize bits) contient suffisamment de bits pour représenter l'entier de seize bits décrit par le normes (citées ci-dessous). Ce n'est pas nécessairement une information utile, n'est-ce pas? Allons plus loin ...


Représentation entière

Les C norme spécifie la précision / gamme minimum pour tous les types entiers standard (et CHAR_BIT, aussi, FWIW) ici . À partir de là, nous pouvons déduire un minimum pour le nombre de bits requis pour stocker la valeur , mais nous pouvons tout aussi bien choisir nos variables en fonction de plages . Néanmoins, une grande partie des détails requis pour cette réponse réside ici. Par exemple, ce qui suit que la norme unsigned intnécessite (au moins) seize bits de stockage:

UINT_MAX                                65535 // 2¹⁶ - 1

Ainsi, nous pouvons voir qu'il unsigned intfaut ( au moins ) 16 bits , c'est là que vous obtenez les deux octets (en supposant que CHAR_BITc'est 8) ... et plus tard, lorsque cette limite est passée à 2³² - 1, les gens déclaraient 4 octets à la place. Ceci explique les phénomènes que vous avez observés:

La plupart des manuels disent que les variables entières occupent 2 octets. Mais lorsque j'exécute un programme imprimant les adresses successives d'un tableau d'entiers, il montre la différence de 4.

Vous utilisez un ancien manuel et compilateur qui vous enseigne le C non portable; l'auteur qui a écrit votre manuel pourrait même ne pas être au courant CHAR_BIT. Vous devriez mettre à jour votre manuel (et votre compilateur) et vous efforcer de vous rappeler que l'informatique est un domaine en constante évolution sur lequel vous devez garder une longueur d'avance pour rivaliser ... Assez parlé de cela, cependant; voyons quels autres secrets non portables stockent ces octets entiers sous-jacents ...

Les bits de valeur sont ce que les idées fausses courantes semblent compter. L'exemple ci-dessus utilise un unsignedtype entier qui ne contient généralement que des bits de valeur, il est donc facile de rater le diable dans les détails.

Bits de signe ... Dans l'exemple ci-dessus, j'ai cité UINT_MAXla limite supérieure unsigned intcar c'est un exemple trivial pour extraire la valeur 16du commentaire. Pour les types signés, afin de faire la distinction entre les valeurs positives et négatives (c'est le signe), nous devons également inclure le bit de signe.

INT_MIN                                -32768 // -(2¹⁵)
INT_MAX                                +32767 // 2¹⁵ - 1

Bits de remplissage ... Bien qu'il soit rare de rencontrer des ordinateurs qui ont des bits de remplissage en nombres entiers, la norme C permet que cela se produise; certaines machines (c'est-à - dire celle-ci ) implémentent des types d'entiers plus grands en combinant deux valeurs entières plus petites (signées) ensemble ... et lorsque vous combinez des entiers signés, vous obtenez un bit de signe perdu. Ce bit gaspillé est considéré comme du remplissage en C. D'autres exemples de bits de remplissage peuvent inclure des bits de parité et des bits d'interruption .


Comme vous pouvez le voir, la norme semble encourager la prise en compte de plages telles que INT_MIN.. INT_MAXet d' autres valeurs minimales / maximales de la norme lors du choix des types d'entiers, et déconseille de s'appuyer sur les tailles car il y a d'autres facteurs subtils susceptibles d'être oubliés tels que les CHAR_BITbits de remplissage qui pourrait affecter la valeur de sizeof (int)(c'est-à-dire que les idées fausses courantes sur les entiers à deux et quatre octets négligent ces détails).

Flimzy
la source
13

Projet standard C99 N1256

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

La taille de intet tous les autres types d'entiers sont définis par l'implémentation, C99 spécifie uniquement:

  • garanties de taille minimale
  • tailles relatives entre les types

5.2.4.2.1 "Tailles des types entiers <limits.h>" donne les tailles minimales:

1 [...] Leurs valeurs définies par la mise en œuvre doivent être égales ou supérieures en grandeur (valeur absolue) à celles indiquées [...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 - 1
  • ULLONG_MAX 18446744073709551615 // 2 64-1

6.2.5 "Types" dit alors:

8 Pour deux types d'entiers quelconques ayant la même signature et un rang de conversion d'entier différent (voir 6.3.1.1), la plage de valeurs du type avec un rang de conversion d'entier plus petit est une sous-plage des valeurs de l'autre type.

et 6.3.1.1 "Booléen, caractères et entiers" détermine les rangs de conversion relatifs:

1 Chaque type entier a un rang de conversion entier défini comme suit:

  • Le rang de long long int sera plus grand que le rang de long int, qui sera supérieur au rang de int, qui sera supérieur au rang de short int, qui sera supérieur au rang de car signé.
  • Le rang de tout type entier non signé doit être égal au rang du type entier signé correspondant, le cas échéant.
  • Pour tous les types d'entiers T1, T2 et T3, si T1 a un rang supérieur à T2 et T2 a un rang supérieur à T3, alors T1 a un rang supérieur à T3
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
8

Les seules garanties sont que chardoivent être au moins 8 bits de large, shortet intdoit être au moins 16 bits de large et longdoit être au moins 32 bits de large, et que sizeof (char)<= sizeof (short)<= sizeof (int)<= sizeof (long)(est de même pour les versions non signées de ces types ).

int peut avoir une largeur comprise entre 16 et 64 bits selon la plate-forme.

John Bode
la source
6

La taille de C «int» est-elle de 2 octets ou 4 octets?

La réponse est «oui» / «non» / «peut-être» / «peut-être pas».

Le langage de programmation C spécifie ce qui suit: la plus petite unité adressable, connue charet également appelée "octet" , a exactement une CHAR_BITlargeur de bits, où CHAR_BITest au moins 8.

Ainsi, un octet en C n'est pas forcément un octet , c'est-à-dire 8 bits. Dans le passé, l'une des premières plates-formes à exécuter du code C (et Unix) avait 4 octets int- mais au total intavait 36 ​​bits, car CHAR_BITc'était 9!

intest censé être la taille entière naturelle de la plate-forme dont la plage est d' au moins-32767 ... 32767 . Vous pouvez obtenir la taille des intoctets de la plate-forme avec sizeof(int); lorsque vous multipliez cette valeur par CHAR_BITvous saurez quelle est sa largeur en bits.


Alors que les machines 36 bits sont pour la plupart mortes, il existe encore des plates-formes avec des octets non 8 bits. Hier encore, il y avait une question sur un MCU Texas Instruments avec des octets 16 bits , qui a un compilateur compatible C99, C11.

Sur TMS320C28x, il semble que char, shortet intsont tous de 16 bits de large, et donc un octet. long intest de 2 octets et de long long int4 octets. La beauté de C est que l'on peut toujours écrire un programme efficace pour une plate-forme comme celle-ci, et même le faire de manière portable!

Antti Haapala
la source
"parce que CHAR_BIT avait 9 ans!" - Ils avaient un calcul de 362880 bits à l'époque !? Impressionnant.
Josh Desmond
5

Cela dépend principalement de la plate-forme que vous utilisez. Cela dépend d'un compilateur à l'autre. De nos jours, dans la plupart des compilateurs, int est de 4 octets . Si vous voulez vérifier ce que votre compilateur utilise, vous pouvez utiliser sizeof(int).

main()
{
    printf("%d",sizeof(int));
    printf("%d",sizeof(short));
    printf("%d",sizeof(long));
}

La seule chose promis par le compilateur c est que la taille de short doit être égale ou inférieure à int et que la taille de long doit être égale ou supérieure à int.Si la taille de int est 4, alors la taille de short peut être 2 ou 4 mais pas plus que cela est vrai pour long et int. Il dit également que la taille du court et du long ne peut pas être la même.

Justpraveen
la source
1
Utiliser %dpour un size_tparamètre est UB.
Paul R
3

Cela dépend de l'implémentation, mais généralement sur x86 et d'autres architectures populaires comme les ARM intprennent 4 octets. Vous pouvez toujours vérifier au moment de la compilation en utilisant sizeof(int)ou tout autre type que vous souhaitez vérifier.

Si vous voulez vous assurer d'utiliser un type d'une taille spécifique, utilisez les types dans <stdint.h>

slartibartfast
la source
2
#include <stdio.h>

int main(void) {
    printf("size of int: %d", (int)sizeof(int));
    return 0;
}

Cela renvoie 4, mais cela dépend probablement de la machine.

les lois
la source
1

La taille de C «int» est-elle de 2 octets ou 4 octets?

Une variable Integer en C occupe-t-elle 2 octets ou 4 octets?

C permet aux "octets" d'être autre chose que 8 bits par "octet".

CHAR_BIT nombre de bits pour le plus petit objet qui n'est pas un champ de bits (octet) C11dr §5.2.4.2.1 1

Une valeur supérieure à 8 est de plus en plus rare. Pour une portabilité maximale, utilisez CHAR_BITplutôt que 8. La taille d'un inten bits en C est sizeof(int) * CHAR_BIT.

#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);

De quels facteurs cela dépend-il?

La inttaille en bits est généralement de 32 ou 16 bits. C plages minimales spécifiées :

valeur minimale pour un objet de type int INT_MIN-32767
valeur maximale pour un objet de type int INT_MAX+32767
C11dr §5.2.4.2.1 1

La plage minimale pour intforce la taille de bits à au moins 16 - même si le processeur était "8 bits". Une taille comme 64 bits est vue dans les processeurs spécialisés. D'autres valeurs comme 18, 24, 36, etc. se sont produites sur des plates-formes historiques ou sont au moins théoriquement possibles. Le codage moderne s'inquiète rarement intdes tailles de bits autres que la puissance de 2 .

Le processeur et l'architecture de l' intordinateur déterminent la sélection de la taille en bits.

Pourtant, même avec des processeurs 64 bits, la inttaille du compilateur peut être de 32 bits pour des raisons de compatibilité car les bases de code volumineuses dépendent du format int32 bits (ou 32/16).

chux - Réintégrer Monica
la source
-1

C'est une bonne source pour répondre à cette question.

Mais cette question est une sorte de toujours vérité répondant «Oui. Les deux».

Cela dépend de votre architecture. Si vous comptez travailler sur une machine 16 bits ou moins, cela ne peut pas être 4 octets (= 32 bits). Si vous travaillez sur une machine 32 bits ou supérieure, sa longueur est de 32 bits.

Pour comprendre, préparez votre programme à produire quelque chose de lisible et utilisez la fonction "sizeof". Cela renvoie la taille en octets de votre type de données déclaré. Mais soyez prudent en utilisant cela avec des tableaux.

Si vous déclarez, int t[12];il renverra 12 * 4 octets. Pour obtenir la longueur de ce tableau, utilisez simplement sizeof(t)/sizeof(t[0]). Si vous allez créer une fonction, qui devrait calculer la taille d'un tableau d'envoi, rappelez-vous que si

typedef int array[12];
int function(array t){
    int size_of_t = sizeof(t)/sizeof(t[0]);
    return size_of_t;
}
void main(){
    array t = {1,1,1};  //remember: t= [1,1,1,0,...,0]
    int a = function(t);    //remember: sending t is just a pointer and equal to int* t
   print(a);   // output will be 1, since t will be interpreted as an int itselve. 
}

Donc, cela ne retournera même pas quelque chose de différent. Si vous définissez un tableau et essayez d'obtenir la longueur par la suite, utilisez sizeof. Si vous envoyez un tableau à une fonction, rappelez-vous que la valeur d'envoi n'est qu'un pointeur sur le premier élément. Mais dans le cas un, vous savez toujours quelle taille votre tableau a. Le cas deux peut être résolu en définissant deux fonctions et en manquant certaines performances. Définissez la fonction (tableau t) et définissez la fonction2 (tableau t, int size_of_t). Appelez "function (t)", mesurez la longueur par un travail de copie et envoyez le résultat à function2, où vous pouvez faire ce que vous voulez sur des tableaux de tailles variables.

Shalec
la source
Le lien fourni est une mauvaise source d'informations car il suppose des choses qui ne sont pas toujours vraies (par exemple, chartoujours signed)
Andrei Damian-Fekete