Existe-t-il des limites de taille pour les structures en C?
De la norme C:
5.2.4.1 Limites de traduction
1 L’implémentation doit être capable de traduire et d’exécuter au moins un programme contenant au moins une instance de chacune des limites suivantes:
… – 65 535 octets dans un object (dans un environnement hébergé uniquement)
… – 1023 membres dans une seule structure ou union
… – 63 niveaux de définitions de structure ou d’union nestedes dans une seule liste de struct-déclaration … 13) Les implémentations doivent éviter autant que possible d’imposer des limites de traduction fixes.
En dehors de cela, la limite supérieure est SIZE_MAX
(valeur maximale pour size_t
).
Étant donné que l’opérateur sizeof
size_t
un résultat de type size_t
, la limite doit être SIZE_MAX
.
Vous pouvez déterminer la valeur de SIZE_MAX
comme ceci:
#include #include int main (void) { printf("%zu", SIZE_MAX); return 0; }
C’est ce que le compilateur devrait autoriser. Ce que l’environnement d’exécution permet, c’est une autre histoire.
Déclarer un object de taille similaire sur la stack (localement) en pratique ne fonctionnera pas car la stack est probablement beaucoup, beaucoup plus petite que SIZE_MAX
.
Avoir un tel object globalement pourrait amener le chargeur exécutable à se plaindre au démarrage du programme.
Analyse empirique
En pratique, des implémentations telles que GCC semblent n’autoriser que les structures inférieures à size_t
, éventuellement liées par PTRDIFF_MAX
. Voir aussi: Quelle est la taille maximale d’un tableau en C?
En utilisant:
for i in `seq 32`; do printf "typedef struct { S$ix; S$iy; } S$(($i+1));\n"; done
Nous faisons le programme:
#include #include typedef struct { uint8_t i; } S0; typedef struct { S0 x; S0 y; } S1; typedef struct { S1 x; S1 y; } S2; typedef struct { S2 x; S2 y; } S3; typedef struct { S3 x; S3 y; } S4; typedef struct { S4 x; S4 y; } S5; typedef struct { S5 x; S5 y; } S6; typedef struct { S6 x; S6 y; } S7; typedef struct { S7 x; S7 y; } S8; typedef struct { S8 x; S8 y; } S9; typedef struct { S9 x; S9 y; } S10; typedef struct { S10 x; S10 y; } S11; typedef struct { S11 x; S11 y; } S12; typedef struct { S12 x; S12 y; } S13; typedef struct { S13 x; S13 y; } S14; typedef struct { S14 x; S14 y; } S15; typedef struct { S15 x; S15 y; } S16; typedef struct { S16 x; S16 y; } S17; typedef struct { S17 x; S17 y; } S18; typedef struct { S18 x; S18 y; } S19; typedef struct { S19 x; S19 y; } S20; typedef struct { S20 x; S20 y; } S21; typedef struct { S21 x; S21 y; } S22; typedef struct { S22 x; S22 y; } S23; typedef struct { S23 x; S23 y; } S24; typedef struct { S24 x; S24 y; } S25; typedef struct { S25 x; S25 y; } S26; typedef struct { S26 x; S26 y; } S27; typedef struct { S27 x; S27 y; } S28; typedef struct { S28 x; S28 y; } S29; typedef struct { S29 x; S29 y; } S30; /*typedef struct { S30 x; S30 y; } S31;*/ S30 s; int main(void) { printf("%jx\n", (uintmax_t)sizeof(s)); return 0; }
puis à Ubunbu le 17.10:
$ arm-linux-gnueabi-gcc --version arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ arm-linux-gnueabi-gcc -std=c99 main.c
travaux. Mais si nous décommentons S31
, il échoue avec:
main.c:35:16: error: type 'struct ' is too large typedef struct { S30 x; S30 y; } S31;
La taille maximale est donc comprise entre 2 ^ 30 et (2 ^ 31 – 1).
Ensuite, nous pouvons convertir S30
en:
typedef struct { S29 x; S29 y; uint8_t a[(2lu << 29) - 1]; } S30;
et avec cela, nous déterminons que la taille maximale est en fait de 2^31 - 1 == PTRDIFF_MAX
sur cette implémentation.