Can sizeof renvoie 0 (zéro)

Est-il possible que l’opérateur sizeof retourne jamais 0 (zéro) en C ou en C ++? Si c’est possible, est-ce correct du sharepoint vue des normes?

En C ++, une classe ou une structure vide a une sizeof au moins 1 par définition. A partir du standard C ++, 9/3 “Classes”: “Les objects complets et les sous-objects membres de type classe auront une taille non nulle.”

En C, une structure vide n’est pas autorisée, sauf par extension (ou une faille dans le compilateur).

Ceci est une conséquence de la grammaire (qui exige qu’il y ait quelque chose à l’intérieur des accolades) avec cette phrase du 6.7.2.1/7 “Spécificateurs de structure et d’union”: “Si la liste de struct-declaration ne contient aucun membre nommé, le comportement est indéfini “.

Si une structure de taille zéro est autorisée, alors c’est une extension de langue (ou une faille dans le compilateur). Par exemple, dans GCC, l’extension est documentée dans “Structures sans membres” , qui dit:

GCC permet à une structure C de ne pas avoir de membres:

  struct empty { }; 

La structure aura une taille zéro. En C ++, les structures vides font partie du langage. G ++ traite les structures vides comme si elles avaient un seul membre de type char .

sizeof ne renvoie jamais 0 en C et en C ++. Chaque fois que vous voyez sizeof évaluer 0 c’est un bug / glitch / extension d’un compilateur spécifique qui n’a rien à voir avec le langage.

Chaque object en C doit avoir une adresse unique. Autrement dit, une adresse ne doit pas contenir plus d’un object d’un type donné (pour que le déréférencement du pointeur fonctionne). Cela étant dit, considérez une structure ‘vide’:

 struct emptyStruct {}; 

et, plus précisément, un éventail d’entre eux:

 struct emptyStruct array[10]; struct emptyStruct* ptr = &array[0]; 

Si les objects étaient en effet vides (c’est-à-dire if sizeof(struct emptyStruct) == 0 ), alors ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr , ce qui n’a pas de sens. Quel object se référerait alors à ptr[0] ou ptr[1] ?

Même si une structure n’a pas de contenu, le compilateur devrait le traiter comme s’il s’agissait d’un octet de longueur afin de conserver le principe “une adresse, un object”.

La spécification du langage C (section A7.4.8) qualifie cette exigence de

Lorsqu’il est appliqué à une structure ou à une union, le résultat (de l’opérateur sizeof ) est le nombre d’octets dans l’object, y compris tout remplissage requirejs pour que l’object soit associé à un tableau.

Comme un octet de remplissage doit être ajouté à un object “vide” pour qu’il fonctionne dans un tableau, sizeof() doit donc renvoyer une valeur d’au moins 1 pour toute entrée valide.

Edit: La section A8.3 de la spécification C appelle une structure sans liste de membres de type incomplet , et la définition de sizeof spécifiquement indique (avec une emphase ajoutée):

L’opérateur (sizeof) ne peut pas être appliqué à un opérande de type fonction, ou de type incomplet , ou à un champ binary.

Cela impliquerait que l’utilisation de sizeof sur une structure vide serait tout aussi invalide que si vous l’utilisiez sur un type de données non défini. Si votre compilateur autorise l’utilisation de structures vides, sachez que l’utilisation de sizeof sur celles-ci n’est pas autorisée conformément à la spécification C. Si votre compilateur vous permet de le faire de toute façon, sachez qu’il s’agit d’un comportement non standard qui ne fonctionnera pas sur tous les compilateurs. ne comptez pas sur ce comportement.

Edit: Voir aussi cette entrée dans la FAQ de Bjarne Stroustrup.

Structures vides, comme le mentionne Isbadawi . De plus, gcc autorise les tableaux de taille 0 :

 int a[0]; sizeof(a); 

EDIT: Après avoir vu le lien MSDN, j’ai essayé la structure vide dans VS2005 et sizeof est revenu 1. Je ne suis pas sûr que ce soit un bug VS ou si la spécification est quelque peu flexible sur ce genre de chose

à mon avis, il est préférable que sizeof renvoie 0 pour une structure de taille 0 (dans l’esprit de c). mais alors le programmeur doit faire attention quand il prend la taille d’une structure vide.

mais cela peut causer un problème. quand le tableau de telles structures est défini, alors

& arr [1] == & arr [2] == & arr [0]

ce qui les fait perdre leur identité.

Je suppose que cela ne répond pas directement à votre question, que ce soit possible ou non. bien que cela puisse être possible en fonction du compilateur. (comme dit dans la réponse de Michael ci-dessus).

 typedef struct { int : 0; } x; x x1; x x2; 

Sous MSVC 2010 (/ Za / Wall):

 sizeof(x) == 4 &x1 != &x2 

Sous GCC (-ansi -pedantic -Wall):

 sizeof(x) == 0 &x1 != &x2 

Par exemple, même si la taille de GCC est nulle, les instances de la structure ont des adresses distinctes.

ANSI C (C89 et C99 – Je n’ai pas regardé C ++) dit “Il sera possible d’exprimer l’adresse de chaque octet individuel d’un object de manière unique.” Cela semble ambigu dans le cas d’un object de taille zéro, car il n’y a pas d’octets.

Edit: “Une déclaration de champ de bits sans déclarateur, mais uniquement un deux-points et une largeur, indique un champ de bits sans nom. Comme cas particulier, un champ de bits d’une largeur de 0 indique qu’aucun autre champ de bits doit être emballé dans l’unité dans laquelle le champ de bits précédent, le cas échéant, a été placé. ”

Je pense qu’il ne retourne jamais 0 dans c, aucune structure vide n’est autorisée

Voici un test, où la taille donne 0

 #include  void func(int i) { int vla[i]; printf ("%u\n",(unsigned)sizeof vla); } int main(void) { func(0); return 0; } 

Si vous avez ceci:

 struct Foo {}; struct Bar { Foo v[]; } 

g++ -ansi renvoie sizeof (Bar) == 0. Comme le fait le compilateur clang & intel.

Cependant, cela ne comstack pas avec gcc. Je déduis que c’est une extension C ++.

 struct Empty { } em; struct Zero { Empty a[0]; } zr; printf("em=%d\n", sizeof(em)); printf("zr=%d\n", sizeof(zr)); 

Résultat:

 em=1 zr=0