tableau de type void
plaine C disposent d'une fonctionnalité intéressante - les pointeurs de type void, qui peut être utilisé comme pointeur vers n'importe quel type de données.
Mais, supposons que j'ai structure suivante:
struct token {
int type;
void *value;
};
où la valeur du champ peut pointer vers char tableau, ou int, ou quelque chose d'autre.
Donc, lors de l'attribution nouvelle instance de cette structure, j'ai besoin de:
1) alloue de la mémoire pour ce struct;
2) allouer de la mémoire pour la valeur et l'affecter à la valeur du champ.
Ma question est, est-il possible de déclarer "array de type void", qui peut être utilisé pour tout autre type void pointeur?
Tout ce que je veux est d'utiliser des "flexible membre de tableau" (décrit dans 6.7.2.1 standard C99) avec la possibilité de casting pour n'importe quel type.
Quelque chose comme ceci:
struct token {
int type;
void value[];
};
struct token *p = malloc(sizeof(struct token) + value_size);
memcpy(p->value, val, value_size);
...
char *ptr = token->value;
Je suppose déclarant jeton->valeur de type char ou int tableau et la conversion de types nécessaire plus tard va faire ce travail, mais peut être très déroutant pour quelqu'un qui va lire ce code plus tard.
- Double pointeurs?
- à l'aide de
char[]
est très bien à mon humble avis, depuissizeof(char) == 1
et vous ne serez jamais surpris. Vous pourriez envisager de macros pour accéder àp->value
avec le type correct.
Vous devez vous connecter pour publier un commentaire.
Bien, en quelque sorte, mais ce n'est probablement pas quelque chose que vous voulez:
La macro suivante peut être utilisée pour l'indexation de vos données (en supposant que
x
est unstruct token *
):Et, si vous le souhaitez, la macro suivante peut envelopper votre
make_token
fonction de la rendre un peu plus intuitive (ou plus hackish, si vous pensez à ce sujet de cette façon):Utilisation:
Je serais probablement ce faire:
modifier, en fait, vous avez à transtypage de ces p.valeur[index] = somethings. Et/ou de l'utilisation d'un syndicat de ne pas avoir à transtypage.
p.value
avant de l'utiliser.p.value[0] = something
produira une erreur de compilation, sûrement? On ne peut déréférencer unvoid*
.void *
pointeurs (comme une extension), mais tous de leur interdire de déférence vide pointeurs.Vous ne pouvez pas avoir un tableau de 'void' articles, mais vous devriez être capable de faire quelque chose comme ce que vous voulez, tant que vous savez value_size quand vous ne le malloc. Mais il ne sera pas assez.
Noter que vous avez besoin d'une adresse de l'opérateur lorsque vous voulez obtenir de l'espace de stockage supplémentaire.
Ce sera "déchets", sizeof(void*) octets, et le type original de
value
n'a pas vraiment d'importance, de sorte que vous pourriez aussi bien utiliser un plus petit élément. Je serais probablementtypedef char placeholder;
et fairevalue
ce type.Expansion sur AShelly de réponse, vous pouvez le faire;
Notez l'utilisation de "offsetof()" au lieu de "sizeof()" lors de l'allocation de la mémoire pour éviter de gaspiller de l' "void *buf;" taille du champ. Le type de "buf" n'a pas beaucoup d'importance, mais à l'aide de "void *" signifie qu'il va aligner le "buf" champ dans la structure de façon optimale pour un pointeur, l'ajout de rembourrage avant si nécessaire. Généralement, cela donne un meilleur alignement de la mémoire pour les entrées, en particulier si elles sont au moins aussi grand que un pointeur.
Accéder les entrées dans la mémoire tampon ressemble à ceci;
Note l'adresse de l'opérateur pour obtenir l'adresse de la "buf" champ comme le point de départ de l'allocation d'entrée de la mémoire.
buffer_t *p = malloc(offsetof(buffer_t, buf) + count*size);
n'avez-vous pas besoin d'ajouter uncount * sizeof(int)
pour tenir compte de lacount
champ dans la structure? Ou êtes-vous en supposant que lesize
champ comprend déjà la taille de laint
?structure suivante peut vous aider.
Plus De Détails : clibutils