Juste curieux, que se passe-t-il réellement si je définis un tableau de longueur nulle int array[0];
dans le code? GCC ne se plaint pas du tout.
Exemple de programme
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Clarification
J'essaie en fait de déterminer si les tableaux de longueur nulle initialisés de cette façon, au lieu d'être pointés comme la longueur variable dans les commentaires de Darhazer, sont optimisés ou non.
C'est parce que je dois publier du code dans la nature, donc j'essaie de déterminer si je dois gérer les cas où le SIZE
est défini comme 0
, ce qui se produit dans un code avec une définition statiqueint array[SIZE];
J'ai été en fait surpris que GCC ne se plaint pas, ce qui a conduit à ma question. D'après les réponses que j'ai reçues, je pense que l'absence d'avertissement est en grande partie due au support de l'ancien code qui n'a pas été mis à jour avec la nouvelle syntaxe [].
Parce que je m'interrogeais principalement sur l'erreur, je marque la réponse de Lundin comme correcte (Nawaz était le premier, mais ce n'était pas aussi complet) - les autres soulignaient son utilisation réelle pour les structures rembourrées par la queue, bien que pertinente, n'est pas t exactement ce que je cherchais.
[]
en Python ou même""
en C? Parfois, vous avez une fonction ou une macro qui nécessite un tableau, mais vous n'avez aucune donnée à y mettre.Réponses:
Un tableau ne peut pas avoir une taille nulle.
ISO 9899: 2011 6.7.6.2:
Le texte ci-dessus est vrai à la fois pour un tableau simple (paragraphe 1). Pour un VLA (variable length array), le comportement n'est pas défini si la valeur de l'expression est inférieure ou égale à zéro (paragraphe 5). Il s'agit d'un texte normatif dans le standard C. Un compilateur n'est pas autorisé à l'implémenter différemment.
gcc -std=c99 -pedantic
donne un avertissement pour le cas non VLA.la source
#error
directive.#error
directive de préprocesseur.Selon la norme, ce n'est pas autorisé.
Cependant, il est courant dans les compilateurs C de traiter ces déclarations comme une déclaration de membre de tableau flexible ( FAM ) :
La syntaxe standard d'un FAM est:
L'idée est que vous l'attribueriez alors ainsi:
Vous pouvez également l'utiliser de manière statique (extension gcc):
Ceci est également connu sous le nom de structures rembourrées en queue (ce terme est antérieur à la publication de la norme C99) ou de struct hack (merci à Joe Wreschnig de l'avoir signalé).
Cependant cette syntaxe n'a été normalisée (et les effets garantis) que récemment en C99. Avant, une taille constante était nécessaire.
1
était la voie portable à suivre, même si c'était plutôt étrange.0
était meilleur pour indiquer l'intention, mais pas légal en ce qui concerne la norme et soutenu en tant qu'extension par certains compilateurs (y compris gcc).Cependant, la pratique du rembourrage de la queue repose sur le fait que le stockage est disponible (prudent
malloc
) et n'est donc pas adapté à l'utilisation de la pile en général.la source
int content[];
ici pour autant que je sache . Puisque je ne suis pas trop averti sur les termes C de l'art ... pouvez-vous confirmer si mon raisonnement semble correct?foo[x]
àfoo[0]
chaque fois qu'ilfoo
s'agissait d'un tableau à un seul élément.En C et C ++ standard, un tableau de taille nulle n'est pas autorisés.
Si vous utilisez GCC, compilez-le avec l'
-pedantic
option. Il donnera un avertissement en disant:Dans le cas de C ++, il donne un avertissement similaire.
la source
error C2466: cannot allocate an array of constant size 0
[BCC32 Error] test.c(3): E2021 Array must have at least one element
-pedantic -Werror
, vous pouvez aussi simplement faire-pedantic-errors
std::array
. (À part: je me souviens, mais je ne peux pas trouver la source que les VLA ont été considérés et explicitement rejetés d'être en C ++.)C'est totalement illégal, et l'a toujours été, mais beaucoup de compilateurs négligent de signaler l'erreur. Je ne sais pas pourquoi vous voulez faire ça. La seule utilisation que je connais est de déclencher une erreur de compilation à partir d'un booléen:
Si
condition
est un faux, alors j'obtiens une erreur de compilation. Parce que les compilateurs le permettent, cependant, j'ai commencé à utiliser:Cela donne une taille de 1 ou -1, et je n'ai jamais trouvé de compilateur qui accepterait une taille de -1.
la source
STATIC_ASSERT
utilisaient.#if condition \n #error whatever \n #endif
J'ajouterai qu'il y a une page entière de la documentation en ligne de gcc sur cet argument.
Quelques citations:
et
pour que tu puisses
et boum :-)
la source
int a[0]
, alorsa[0] = 1
a[1] = 2
??a[100000] = 5
mais si vous êtes chanceux, vous planterez simplement votre application, si vous êtes chanceux: -)Une autre utilisation des tableaux de longueur nulle est de créer des objets de longueur variable (pré-C99). Tableaux de longueur zéro sont différents de réseaux flexibles qui ont [] sans 0.
Cité de gcc doc :
Un exemple concret est celui des tableaux de longueur nulle de
struct kdbus_item
dans kdbus.h (un module du noyau Linux).la source
void*
à des fins d'arithmétique (donc ajouter ou soustraire des pointeurs à des objets de taille zéro serait interdit). Alors que les membres de tableau flexible sont généralement meilleurs que les tableaux de taille zéro, ils peuvent également agir comme une sorte d '"union" pour alias des choses sans ajouter un niveau supplémentaire d'indirection "syntaxique" à ce qui suit (par exemple, étant donné que l'struct foo {unsigned char as_bytes[0]; int x,y; float z;}
on peut accéder aux membresx
...z
...myStruct.asFoo.x
, etc. contenu.sizeof x->contents
est une erreur dans ISO C au lieu de renvoyer 0 dans gcc. Les tableaux de taille zéro qui ne sont pas des membres de structure présentent un tas d'autres problèmes.struct {int n; THING dat[];}
et puisse travailler avec des choses de durée statique ou automatique.Les déclarations de tableau de taille zéro dans les structures seraient utiles si elles étaient autorisées, et si la sémantique était telle que (1) elles forceraient l'alignement mais n'alloueraient pas d'espace, et (2) l'indexation du tableau serait considérée comme un comportement défini dans le cas où le pointeur résultant serait dans le même bloc de mémoire que la structure. Un tel comportement n'a jamais été autorisé par aucun standard C, mais certains compilateurs plus anciens l'ont autorisé avant qu'il ne devienne standard pour les compilateurs d'autoriser les déclarations de tableau incomplètes avec des crochets vides.
Le piratage de structure, tel qu'il est généralement implémenté en utilisant un tableau de taille 1, est douteux et je ne pense pas qu'il soit nécessaire que les compilateurs s'abstiennent de le casser. Par exemple, je m'attendrais à ce que si un compilateur voit
int a[1]
, il serait dans ses droits de considérera[i]
commea[0]
. Si quelqu'un essaie de contourner les problèmes d'alignement du hack struct via quelque chose commeun compilateur peut devenir intelligent et supposer que la taille du tableau est en réalité de quatre:
Une telle optimisation pourrait être raisonnable, surtout si elle
myStruct->data
pouvait être chargée dans un registre dans la même opération quemyStruct->size
. Je ne sais rien dans la norme qui interdirait une telle optimisation, même si bien sûr cela briserait tout code qui pourrait s'attendre à accéder à des éléments au-delà du quatrième élément.la source