Est-il possible de déréférencer un pointeur void sans conversion de type dans le langage de programmation C?
En outre, y a-t-il un moyen de généraliser une fonction qui peut recevoir un pointeur et le stocker dans un pointeur void et en utilisant ce pointeur void, pouvons-nous créer une fonction généralisée?
par exemple:
void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a); // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a); // If character pointer is received
else if(b==3)
printf("%f",*(float*)a); // If float pointer is received
}
Je veux rendre cette fonction générique sans utiliser les instructions if-else - est-ce possible?
De plus, s'il existe de bons articles sur Internet qui expliquent le concept de pointeur vide, il serait avantageux que vous puissiez fournir les URL.
De plus, l'arithmétique des pointeurs avec des pointeurs vides est-elle possible?
la source
void *
pointeurs de la même manière quechar *
, mais ce n'est pas standard et vous ne devriez pas vous y fier.En C, a
void *
peut être converti en un pointeur vers un objet d'un type différent sans conversion explicite:Cela n'aide cependant pas à écrire votre fonction de manière plus générique.
Vous ne pouvez pas déréférencer un
void *
en le convertissant en un autre type de pointeur, car le déréférencement d'un pointeur obtient la valeur de l'objet pointé. Un nuvoid
n'est pas un type valide, ilvoid *
n'est donc pas possible de déréférencer un .L'arithmétique des pointeurs consiste à modifier les valeurs des pointeurs par des multiples des
sizeof
objets pointés. Encore une fois, parce que cevoid
n'est pas un type vrai,sizeof(void)
n'a pas de signification, l'arithmétique du pointeur n'est donc pas valide survoid *
. (Certaines implémentations le permettent, en utilisant l'arithmétique du pointeur équivalent pourchar *
.)la source
void abc(void *a, int b)
. Mais pourquoi ne pas l'utiliservoid abc(int *a, int b)
, car dans votre fonction que vous définirez éventuellementint *test = a;
, cela sauverait une variable, et je ne vois pas d'autres avantages à définir une autre variable. Je vois de nombreux codes écrits de cette manière en utilisantvoid *
comme paramètres et en transposant des variables plus tard dans la fonction. Mais puisque cette fonction est écrite par l'auteur, il doit donc connaître l'utilisation de la variable, pourquoi l'utiliservoid *
? MerciVous devez être conscient qu'en C, contrairement à Java ou C #, il n'y a absolument aucune possibilité de "deviner" avec succès le type d'objet vers
void*
lequel pointe un pointeur. Quelque chose de similaire àgetClass()
n'existe tout simplement pas, car cette information est introuvable. Pour cette raison, le type de "générique" que vous recherchez est toujours accompagné de méta-informations explicites, commeint b
dans votre exemple ou la chaîne de format dans laprintf
famille de fonctions.la source
Un pointeur void est appelé pointeur générique, qui peut faire référence à des variables de n'importe quel type de données.
la source
Jusqu'à présent, ma compréhension du pointeur de vide est la suivante.
Lorsqu'une variable de pointeur est déclarée à l'aide du mot clé void, elle devient une variable de pointeur à usage général. L'adresse de toute variable de tout type de données (char, int, float etc.) peut être affectée à une variable de pointeur void.
Comme un autre pointeur de type de données peut être affecté au pointeur void, je l'ai donc utilisé dans la fonction absolut_value (code ci-dessous). Pour faire une fonction générale.
J'ai essayé d'écrire un code C simple qui prend un entier ou un flottant comme argument et essaie de le rendre + ve, s'il est négatif. J'ai écrit le code suivant,
Mais j'obtenais une erreur, alors j'ai appris que ma compréhension du pointeur de vide n'était pas correcte :(. Alors maintenant, je vais passer à collecter des points pourquoi.
Ce que j'ai besoin de mieux comprendre sur les pointeurs vides, c'est que.
Nous devons transtyper la variable de pointeur void pour la déréférencer. Cela est dû au fait qu'un pointeur void n'a aucun type de données associé. Il n'y a aucun moyen pour le compilateur de savoir (ou de deviner?) Quel type de données est pointé par le pointeur void. Donc, pour prendre les données pointées par un pointeur void, nous les avons typées avec le type correct des données contenues dans l'emplacement des pointeurs vides.
Un pointeur void peut être vraiment utile si le programmeur n'est pas sûr du type de données des données entrées par l'utilisateur final. Dans un tel cas, le programmeur peut utiliser un pointeur vide pour pointer vers l'emplacement du type de données inconnu. Le programme peut être réglé de manière à demander à l'utilisateur d'informer le type de données et la diffusion de type peut être effectuée en fonction des informations entrées par l'utilisateur. Un extrait de code est donné ci-dessous.
Un autre point important que vous devez garder à l'esprit à propos des pointeurs vides est que - l'arithmétique des pointeurs ne peut pas être exécutée dans un pointeur vide.
Alors maintenant, j'ai compris quelle était mon erreur. Je corrige la même chose.
Références :
http://www.antoarts.com/void-pointers-in-c/
http://www.circuitstoday.com/void-pointers-in-c .
Le nouveau code est comme indiqué ci-dessous.
Merci,
la source
Non ce n'est pas possible. Quel type doit avoir la valeur déréférencée?
la source
la source
printf
. Cette réponse a un bon exemple pour cela.int b
par une énumération, mais toute modification ultérieure de cette énumération interromprait cette fonction.La seule façon simple que je vois est d'utiliser la surcharge .. qui n'est pas disponible dans le langage de programmation C AFAIK.
Avez-vous pensé au langage de programmation C ++ pour votre programme? Ou y a-t-il une contrainte qui interdit son utilisation?
la source
Voici un bref pointeur sur les
void
pointeurs: https://www.learncpp.com/cpp-tutorial/613-void-pointers/En supposant que la mémoire de la machine est octet adressable et ne requiert pas accès alignés, la plus générique et atomique (plus proche de la représentation du niveau de la machine) manière d'interpréter un
void*
est un pointeur sur un octet,uint8_t*
. Le cast de avoid*
en auint8_t*
vous permettrait, par exemple, d'imprimer les premiers 1/2/4/8 / autant que vous le désirez en commençant à cette adresse, mais vous ne pouvez pas faire grand chose d'autre.la source
Vous pouvez facilement imprimer une imprimante vide
la source
void
a la même taille queint
?void
pointeur, c'est d'imprimer leint
à l'adresse mémoire que le pointeur contient (qui dans ce cas serait la valeur dep
).Comme C est un langage à typage statique et fortement typé, vous devez décider du type de variable avant la compilation. Lorsque vous essayez d'émuler des génériques en C, vous finirez par essayer de réécrire à nouveau C ++, il serait donc préférable d'utiliser C ++ à la place.
la source
Le pointeur void est un pointeur générique. L'adresse de n'importe quel type de données de n'importe quelle variable peut être assignée à un pointeur void.
la source
Vous ne pouvez pas déréférencer un pointeur sans spécifier son type car différents types de données auront des tailles différentes en mémoire, c'est-à-dire qu'un entier vaut 4 octets, un caractère vaut 1 octet.
la source
Fondamentalement, en C, les «types» sont un moyen d'interpréter les octets en mémoire. Par exemple, ce que le code suivant
Dit "Quand j'exécute main, je veux allouer 4 (taille de l'entier) + 4 (taille de l'entier) = 8 (octets totaux) de mémoire. Quand j'écris '.x' comme lvalue sur une valeur avec l'étiquette de type Pointez au moment de la compilation, récupérez les données à partir de l'emplacement mémoire du pointeur plus quatre octets. Donnez à la valeur de retour l'étiquette de compilation "int".
À l'intérieur de l'ordinateur au moment de l'exécution, votre structure "Point" ressemble à ceci:
Et voici à quoi
void*
pourrait ressembler votre type de données: (en supposant un ordinateur 32 bits)la source
Cela ne fonctionnera pas, mais void * peut beaucoup aider à définir un pointeur générique vers des fonctions et à le transmettre en tant qu'argument à une autre fonction (similaire au callback en Java) ou à lui définir une structure similaire à oop.
la source