Votre intension sur "pourquoi ne pas utiliser un tableau de taille 1" est parfaite.
Le code effectue le "C struct hack" incorrect, car les déclarations de tableaux de longueur nulle sont une violation de contrainte. Cela signifie qu'un compilateur peut rejeter votre piratage dès la compilation au moment de la compilation avec un message de diagnostic qui arrête la traduction.
Si nous voulons perpétrer un hack, nous devons le faufiler devant le compilateur.
La bonne façon de faire le « C hack struct » (qui est compatible avec les dialectes C vont revenir à 1989 ANSI C, et probablement beaucoup plus tôt) est d'utiliser un tableau parfaitement valable de la taille 1:
struct someData
{
int nData;
unsigned char byData[1];
}
de plus, au lieu de sizeof struct someData
, la taille de la pièce avant byData
est calculée à l'aide:
offsetof(struct someData, byData);
allouer un struct someData
avec un espace pour 42 octets dans byData
, nous pourrions alors utiliser:
struct someData *psd = (struct someData *) malloc(offsetof(struct someData, byData) + 42);
Notez que ce calcul offsetof
est en fait le calcul correct même dans le cas de la taille du tableau étant égal à zéro. Vous voyez, sizeof
la structure entière peut inclure le remplissage. Par exemple, si nous avons quelque chose comme ceci:
struct hack {
unsigned long ul;
char c;
char foo[0]; /* assuming our compiler accepts this nonsense */
};
La taille de struct hack
est tout à fait peut-être rembourré pour l'alignement en raison de l'organe ul
. Si unsigned long
est quatre octets de large, alors très probablement sizeof (struct hack)
est 8, alors que offsetof(struct hack, foo)
est presque certainement 5. La méthode offsetof
est la façon d'obtenir la taille précise de la partie précédente de la structure juste avant le tableau.
Donc, ce serait le moyen de refactoriser le code: le rendre conforme à la structure classique et hautement portable.
Pourquoi ne pas utiliser un pointeur? Parce qu'un pointeur occupe un espace supplémentaire et doit être initialisé.
Il existe d'autres bonnes raisons de ne pas utiliser un pointeur, à savoir qu'un pointeur nécessite un espace d'adressage pour être significatif. La struct hack est extériorisable: c'est-à-dire qu'il existe des situations dans lesquelles une telle mise en page est conforme au stockage externe tel que des zones de fichiers, paquets ou mémoire partagée, dans lesquelles vous ne voulez pas de pointeurs.
Il y a plusieurs années, j'ai utilisé le hack struct dans une interface de transmission de message de mémoire partagée entre le noyau et l'espace utilisateur. Je ne voulais pas de pointeurs là-bas, car ils n'auraient eu de sens que pour l'espace d'adressage d'origine du processus générant un message. La partie noyau du logiciel avait une vue sur la mémoire en utilisant son propre mapping à une adresse différente, et tout était basé sur des calculs de décalage.
Ceci est le "struct hack", décrit à la question 2.6 de la [FAQ comp.lang.c] (http://www.c-faq.com/). Dennis Ritchie l'a qualifié de «chumminess injustifié avec la mise en œuvre du C». C99 a introduit une nouvelle fonctionnalité de langage, le "membre de tableau flexible", pour remplacer le hack struct. Même le compilateur de Microsoft, qui est noté pour son manque de prise en charge de C99, prend en charge les membres de groupe flexibles. –
N'ajoutez PAS le tag 'c' à cette question.Les règles C++ pour cela sont assez différentes des règles C. –
@BenVoigt La réponse acceptée est le code C pur, donc je suppose que votre édition est erronée. c hack s'applique à c et C++ de la même manière –