Mécanisme interne de taille en C?

J’utilise sizeof pour obtenir la taille d’une structure en C, mais le résultat est inattendu.

struct sdshdr { int len; int free; char buf[]; }; int main(){ printf("struct len:%d\n",(sizeof(struct sdshdr))); return 0; } //struct len:8, with or without buf 

Ma question est la suivante: pourquoi buf n’occupe-t-il aucun espace et pourquoi la taille du type int toujours de 4 sur un processeur 64 bits?

voici la sortie de gcc -v :

 Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.4.0 Thread model: posix 

Le [] est un membre de tableau flexible . Ils ne comptent pas dans la taille totale de la structure, car la norme C le dit explicitement:

6.7.2.1/18

En tant que cas particulier, le dernier élément d’une structure avec plus d’un membre nommé peut avoir un type de tableau incomplet; cela s’appelle un membre de tableau flexible. Dans la plupart des cas, le membre de tableau flexible est ignoré. En particulier, la taille de la structure est comme si le membre de tableau flexible était omis, sauf qu’il pouvait avoir plus de remplissage que l’omission impliquerait.

C’est intentionnel, car un membre de groupe flexible a pour but de vous permettre d’allouer dynamicment des données de fin après la structure. (Lorsque la structure est un en-tête de fichier, un en-tête de protocole, etc.)

Exemple incluant une discussion sur les extensions gcc non standard et l’ancien “struct hack” pré-C99.

A partir de C99, la taille d’un tableau à la fin d’une structure peut être omise. Pour les besoins de sizeof(struct) ce tableau semble avoir une taille nulle (bien que sa présence puisse append un peu de remplissage à la structure), mais sa longueur doit être flexible , c.-à-d. la quantité désirée d’espace supplémentaire pour le tableau à la fin. (Pour éviter de sortir des limites, la longueur réelle du tableau doit être stockée quelque part.)

Avant C99, c’était un hack assez courant pour avoir un tableau de taille 1 (ou 0 si le compilateur le permettait) à la fin d’une structure, puis allouer plus d’espace pour cela, donc C99 permettait explicitement cette pratique en introduisant le tableau flexible membre sans taille donnée.

En tant qu’extension GNU c, vous disposez de tableaux de longueur nulle:

En tant qu’extension GNU, le nombre d’éléments peut être aussi petit que zéro. Les tableaux de longueur zéro sont utiles comme dernier élément d’une structure qui est en réalité un en-tête pour un object de longueur variable:

Par exemple, considérons ce code du manuel The gnu c

  struct line { int length; char contents[0]; }; { struct line *this_line = (struct line *) malloc (sizeof (struct line) + this_length); this_line -> length = this_length; } 

Dans ISO C99, vous utiliseriez un membre de tableau flexible, dont la syntaxe et la sémantique sont légèrement différentes:

  • Les membres de tableau flexibles sont écrits sous forme de contenu [] sans le 0.

  • Les membres de tableau flexibles ont un type incomplet, de sorte que la taille de l’opérateur ne peut pas être appliquée. En tant que particularité de l’implémentation initiale des tableaux de longueur nulle, sizeof est évalué à zéro.

  • Les membres de tableau flexibles peuvent uniquement apparaître en tant que dernier membre d’une structure qui est autrement non vide.

  • Une structure contenant un membre de tableau flexible, ou une union contenant une telle structure (éventuellement récursivement), peut ne pas être membre d’une structure ou d’un élément d’un tableau. (Cependant, ces utilisations sont autorisées par GCC en tant qu’extensions.)

buf Voici un flexible array member flexible Les membres de tableau flexibles ont un type incomplet, de sorte que l’opérateur sizeof peut ne pas être appliqué alors que l’implémentation d’origine des zero-length arrays , sizeof evaluates to zero .