12
votes

Plusieurs tableaux de longueur 0 ont la même adresse?

Le code suivant imprime la même adresse pour les deux A et B à l'aide de GCC (non testé avec d'autres compilateurs): xxx

Ma question est que C standard autorise plusieurs variables d'avoir une même adresse ou qu'il s'agit simplement d'une extension de GCC?

c gcc

6 commentaires

Étant donné que les tableaux de longueur zéro sont une extension GCC, le comportement d'une matrice de longueur zéro est également une extension GCC. (Indice: essayez cc -std = c89 -peal -wall -wall x.c ).


@ Robᵩ est-il documenté partout dans les documents de GCC ou de liker?


La norme C n'autorise pas les matrices de longueur zéro. La norme C n'a rien à dire sur les adresses des tableaux de longueur zéro.


Curieux de savoir comment une matrice de longueur zéro serait représentée dans C.


Ils sont dans des champs disjoints, une variable de types (ou différents) pourrait avoir la même adresse.


@ Robᵩ pourquoi c89? Utilisez la norme la plus récente.


4 Réponses :


5
votes

dans la norme C, la matrice de taille zéro n'est pas autorisée.

Si vous le compilez avec une option -pedantic à l'aide de GCC. Cela donnera un avertissement, en disant:

zéro.c: 3: 6: AVERTISSEMENT: ISO C interdit la graisse de taille zéro 'A' [-> Pedantic]


0 commentaires

21
votes

Le paragraphe C11 6.7.6.2P1 dit :

contraintes

  1. En plus des qualificateurs de type optionnels et du mot-clé statique, le [ et ] peut délimiter une expression ou *. S'ils délimitent une expression (qui spécifie la taille d'un tableau), l'expression doit avoir un type d'entier. Si l'expression est une expression constante, il doit avoir une valeur supérieure à zéro .

    Comme votre programme viole un doit (0 n'est pas supérieur à zéro), le programme aurait un comportement indéfini , sauf que dans ce cas, il apparaît dans les contraintes section. Comme la section 4 Conformité dit

    4 Conformité
    1. dans cette norme internationale, "" doit "être interprété comme une exigence sur une mise en œuvre ou sur un programme; Inversement, "ne" doit pas "doit être interprété comme une interdiction.

    2. Si un "" doit "ou" "ne" doit pas "exigence", qui apparaît en dehors d'une contrainte ou d'une contrainte d'exécution est violée, le comportement n'est pas défini. Le comportement non défini est autrement indiqué dans la présente Norme internationale par les mots «comportement non défini» ou par l'omission de toute définition explicite du comportement. Il n'y a pas de différence d'emphase parmi ces trois; Ils décrivent tous «comportement indéfini».

      aussi, le 5.1.1.3p1 < / a> dit:

      1. Une implémentation conforme doit produire au moins un message de diagnostic (identifié de manière définie par la mise en oeuvre) si une unité de traduction de prétraitement ou une unité de traduction «forte> contient une violation de la syntaxe toute syntaxe règle ou contrainte , même si le comportement est également explicitement spécifié comme non défini ou défini par la mise en œuvre. Les messages de diagnostic ne doivent pas nécessairement être produits dans d'autres circonstances. [9])

        avec notes de bas de page Dit:

        9) L'intention est que une mise en œuvre devrait identifier la nature de, et dans la mesure du possible, chaque violation. Bien entendu, une implémentation est libre de produire n'importe quel nombre de diagnostics tant que le programme valide est toujours correctement traduit. il peut également traduire avec succès un programme invalide.


        Ainsi,


0 commentaires

3
votes

Comme d'autres ont déjà dit que les tableaux de longueur ne sont pas autorisés dans le compilateur C & GCC standard lui permettent d'extension. J'aimerais ajouter une chose de plus: le comportement de votre programme que vous avez posté en question est non défini . Vous devez lancer vers void * lors de l'utilisation de% p spécificateur de format, car printf 'S % p Spécificateur de format attend un argument de type vide * .

Voir cette réponse: Printf et pointeurs


6 commentaires

En réalité, cela est discutable, puisque void * et char * est compatible.


@Anttihaapala: la norme le dit-elle?


Ça ne le dit pas dans printf (doit être pointeur sur vide * ); Toutefois Char * et VOID * sont compatibles conformément au VA_ARG .


@Destructeur: C standard dit que vide * et char * Les pointeurs partagent des représentations d'objet identiques et des exigences d'alignement, qui est "destinée à impliquer l'interchangeabilité comme des arguments à des fonctions, de retour des valeurs de retour de fonctions et membres des syndicats "


Notez que la réponse liée utilise int * qui n'est pas garantie pour être compatible.


La norme C peut dire que char * et void * est compatible pour va_arg , mais cela ne dit pas que printf doit être mis en œuvre comme si vous utilisez VA_ARG et "signifiait impliquer l'interchangeabilité comme des arguments" est non normatif. Formellement, le comportement est toujours indéfini.



-2
votes

Ce tableau de longueur zéro est une extension GCC et n'est pas pris en charge par la bibliothèque standard, le comportement dépend de la mise en oeuvre de l'extension GCC

Vous pouvez voir les documents GCC ici

6.17 Des tableaux de longueur zéro

Un réseau de longueur zéro est appelé tableau flexible (code>

  • Les membres de la matrice flexibles sont écrits comme des contenus [] sans 0.
  • Les membres de la matrice flexibles ont un type incomplet, et la taille de la taille de l'opérateur peut ne pas être appliquée. En tant qu'appariement de la mise en oeuvre d'origine des tableaux de longueur zéro, Tailleof évalue à zéro.
  • Les membres de la matrice flexibles ne peuvent apparaître que comme dernier membre d'une structure qui est autrefois non vide.
  • Une structure contenant un organe flexible ou une union contenant une telle structure (éventuellement récursivement) peut ne pas être un élément d'une structure ou d'un élément d'une matrice. (Cependant, ces utilisations sont autorisées par GCC comme extensions.)

1 commentaires

Le code dans la question ne concerne pas les membres de la matrice flexibles.