46 votes

Pourquoi utiliser la taille du tableau 1 au lieu du pointeur?

Dans un projet open source C ++, je vois cela.

 struct SomeClass {
  ...
  size_t data_length;
  char data[1];
  ...
}
 

Quels sont les avantages de le faire plutôt que d'utiliser un pointeur?

 struct SomeClass {
  ...
  size_t data_length;
  char* data;
  ...
}
 

La seule chose à laquelle je peux penser est avec la version de tableau de taille 1, les utilisateurs ne devraient pas voir NULL. Y a-t-il autre chose?

36voto

Johannes Schaub - litb Points 256113

Avec cela, vous n'avez pas à allouer la mémoire, d'ailleurs et de faire le pointeur point à qui.

  • Pas de surcoût de gestion de la mémoire
  • Les accès à la mémoire de frapper la mémoire cache (beaucoup) plus susceptibles

L'astuce consiste à allouer plus de mémoire que d' sizeof (SomeClass), et de faire une SomeClass* point à elle. Puis la mémoire initiale sera utilisé par votre SomeClass de l'objet, et le reste de la mémoire peut être utilisée par l' data. Qui est, vous pouvez dire p->data[0] mais aussi p->data[1] et ainsi de suite jusqu'à ce que vous atteignez la fin de la mémoire allouée.

Les Points peuvent être faites que cette utilisation entraîne un comportement indéfini, parce que vous avez déclaré votre tableau à un seul élément, mais d'y accéder comme s'il contenait plus. Mais réel les compilateurs n'autoriser que ce avec le sens parce que le C++ n'a pas de syntaxe alternative pour formuler ces moyens (C99 a, il est appelé "flexible membre du groupe" là-bas).

19voto

Lyke Points 1374

C'est généralement un moyen rapide (et sale?) D'éviter plusieurs allocations et désallocations de mémoire, bien qu'il soit plus élégant en C que C ++.

Autrement dit, au lieu de cela:

 struct SomeClass *foo = malloc(sizeof *foo);
foo->data = malloc(data_len);
memcpy(foo->data,data,data_len);

....
free(foo->data);
free(foo);
 

Vous faites quelque chose comme ça:

 struct SomeClass *foo = malloc(sizeof *foo + data_len);
memcpy(foo->data,data,data_len);

...
free(foo);
 

En plus d'économiser les appels de (dé) allocation, cela peut également économiser un peu de mémoire car il n'y a pas d'espace pour un pointeur et vous pouvez même utiliser un espace qui aurait autrement pu être un remplissage de structure.

11voto

Ed S. Points 70246

Ils sont sémantiquement différents dans votre exemple.

char data[1] est un tableau de caractères valide avec un élément non initialisé alloué sur la pile. Vous pourriez écrire data[0] = 'w' et votre programme serait correct.

char* data; déclare simplement un pointeur qui n'est pas valide jusqu'à ce qu'il soit initialisé pour pointer vers une adresse valide.

10voto

Ben Zotto Points 32105

Habituellement, vous voyez ce que le dernier membre d'une structure. Alors celui qui l' mallocs de la structure, attribuera tous les octets de données en continu dans la mémoire comme un bloc de "suivre" la structure.

Donc, si vous avez besoin de 16 octets de données, vous souhaitez allouer un exemple comme ceci:

SomeClass * pObj = malloc(sizeof(SomeClass) + (16 - 1));

Ensuite, vous pouvez accéder aux données comme si c'était un tableau:

pObj->data[12] = 0xAB;

Et vous pouvez libérer de tous les trucs avec un appel, bien sûr, en tant que bien.

L' data membre est un élément de tableau, par convention, car les compilateurs C (et, apparemment, l'actuelle norme C++) ne permet pas un zéro-tableau de taille. Nice poursuivre la discussion ici: http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

2voto

Jonathan Wood Points 26443
  1. La structure peut être simplement allouée comme un seul bloc de mémoire au lieu de plusieurs allocations qui doivent être libérées.

  2. Il utilise en fait moins de mémoire car il n'a pas besoin de stocker le pointeur lui-même.

  3. La mise en cache peut également présenter des avantages en termes de performances car la mémoire est contiguë.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X