Comment puis-je utiliser correctement un pointeur void en C?
Quelqu'un peut m'expliquer pourquoi je ne reçois pas la valeur de la variable, mais sa mémoire à la place?
J'ai besoin d'utiliser void* à point "unsigned short" valeurs.
Que je comprends vide pointeurs, leur taille est inconnue et leur type est inconnu.
Une fois les initialiser cependant, ils sont connus, non?
Pourquoi mon instruction printf imprimer la valeur faux?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
La sortie j'obtiens:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
qui printf parlez-vous?
Quelles sont les valeurs que vous attendez-vous, et que faites-vous réellement obtenir?
Il semble que cela fonctionne ici Point de ce qui est inhabituel et il pourrait faire de mieux vous aider.
Je pense que vous avez peut-être un peu fragile sur les pointeurs. Peut-être que ce sera vous aider: beej.us/guide/bgc/output/html/multipage/pointers.html
Quelles sont les valeurs que vous attendez-vous, et que faites-vous réellement obtenir?
Il semble que cela fonctionne ici Point de ce qui est inhabituel et il pourrait faire de mieux vous aider.
Je pense que vous avez peut-être un peu fragile sur les pointeurs. Peut-être que ce sera vous aider: beej.us/guide/bgc/output/html/multipage/pointers.html
OriginalL'auteur user900785 | 2011-12-09
Vous devez vous connecter pour publier un commentaire.
Une chose à garder à l'esprit: C ne garantit pas que
int
sera assez grande pour contenir un pointeur (y comprisvoid*
). Ce moulage est pas un portable chose/une bonne idée. Utilisation%p
àprintf
un pointeur.De même, vous êtes en train de faire un "mauvais casting" ici:
void* res = (int*) a
est de dire au compilateur: "je suis sûr que la valeur dea
est valideint*
, de sorte que vous devez le traiter comme tel". Sauf si vous savez pour un fait qu'il est unint
stockées en mémoire à l'adresse 30, ce qui est faux.Heureusement, vous avez immédiatement remplacer
res
avec l'adresse de la autresa
. (Vous avez deux vars nomméa
et deux nommésres
, cellesmain
et ceux dansfunc
. Ceuxfunc
sont des copies de la valeur de l'un dansmain
, lorsque vous appelez). Généralement parlant, l'écrasement de la valeur d'un paramètre à une fonction est "mauvais", mais il est techniquement légal. Personnellement, je vous recommande de déclarer l'ensemble de vos fonctions de paramètres commeconst
99% du temps (par exemple,void func (const int a, const void* res)
)Puis, vous lancez
res
à ununsigned short
. Je ne pense pas que quelqu'un est encore en cours d'exécution sur la 16 bits de l'espace d'adressage du PROCESSEUR (bien, votre Apple II, peut-être), donc, ça va certainement corrompre la valeur deres
en tronquant.En général, dans C, typecasts sont dangereux. Vous êtes à prendre en compte le compilateur du type de système, et en disant: "regardez ici, Monsieur le Compilateur, je suis le programmeur, et je sais mieux que vous ce que j'ai ici. Donc, vous venez d'être tranquille et que cela se produise." La conversion d'un pointeur à un non-type de pointeur est presque universellement mal. La conversion entre les types de pointeur est le plus souvent mauvais que ne pas.
Je vous suggère de vérifier certains de la "Relative" des liens en bas de cette page afin de trouver un bon aperçu de la façon dont C types de pointeurs de travail, en général. Parfois, il faut lire plus de quelques pour vraiment avoir une compréhension sur la façon dont ce genre de choses va de pair.
OriginalL'auteur BRPocock
est une fonte sur un pointeur, res est une adresse en mémoire, par moulage d'un unsigned short, vous obtenez la valeur de l'adresse comme un unsigned short au lieu de la valeur hexadécimale, afin d'être sûr que vous allez obtenir une valeur correcte, vous pouvez imprimer
La première fonte
(unsigned short*)res
fait un cast survoid*
pointeur vers un pointeur surunsigned short
. Vous pouvez ensuite extraire la valeur à l'intérieur de l'adresse de mémoire res vers par référence à l'aide de la*
OriginalL'auteur Mansuro
Un pointeur void est utilisé dans C comme une sorte de pointeur générique. Un vide pointeur de variable peut être utilisé pour contenir l'adresse d'une variable de type. Le problème avec un pointeur void est une fois que vous avez attribué une adresse du pointeur, les informations sur le type de la variable n'est plus disponible pour le compilateur pour vérifier.
En général, nulle pointeurs devrait être évitée, car le type de la variable dont l'adresse est dans le vide pointeur n'est plus disponible pour le compilateur. D'autre part, il existe des cas où un vide pointeur qui est très pratique. Toutefois, c'est au programmeur de connaître le type de la variable dont l'adresse est dans le vide pointeur de variable et de l'utiliser correctement.
Beaucoup de anciennes de source C a C de style jette entre le type des pointeurs et non avenue des pointeurs. Ce n'est pas nécessaire avec les compilateurs modernes et devrait être évitée.
De la taille d'un pointeur void variable est connue. Ce qui n'est pas connu, c'est la taille de la variable dont le pointeur est dans le vide pointeur de variable. Par exemple, voici quelques exemples de sources.
Une façon qui vide les pointeurs ont été utilisés, c'est d'avoir plusieurs différents types de structures qui sont fournis en argument à une fonction, généralement une sorte de dispatching de la fonction. Depuis l'interface de la fonction qui permet différents types de pointeur, un vide pointeur doit être utilisé dans la liste d'arguments. Ensuite, le type de la variable pointée est déterminé soit par un argument supplémentaire ou de l'inspection de la variable pointée. Un exemple de ce type d'utilisation d'une fonction serait quelque chose comme ce qui suit. Dans ce cas, nous inclure un indicateur comme le type de la structure dans le premier membre de diverses permutations de la struct. Tant que toutes les structures qui sont utilisés avec cette fonction ayant comme premier membre d'une
int
indiquant le type de structure, cela fonctionnera.Quelque chose comme ci-dessus a un certain nombre de problèmes de conception logicielle avec le couplage et la cohésion de sorte que si vous avez de bonnes raisons pour l'utilisation de cette approche, il est préférable de repenser la conception de votre. Cependant, le langage de programmation C vous permet de faire cela.
Il y a certains cas où le vide pointeur est nécessaire. Par exemple, le
malloc()
fonction qui alloue de la mémoire renvoie un void pointeur contenant l'adresse de la zone qui leur a été attribué (ou la valeur NULL si l'allocation a échoué). Le vide pointeur dans ce cas permet à unmalloc()
fonction qui permet de retourner l'adresse de la mémoire pour n'importe quel type de variable. Le tableau suivant montre l'utilisation demalloc()
avec différents types de variables.OriginalL'auteur Richard Chambers
Si ce que vous voulez faire est de passer la variable
a
par nom et de l'utiliser, essayez quelque chose comme:Si vous obtenez une
void*
à partir d'une fonction de la bibliothèque, et vous savez que son type réel, vous devez immédiatement le stocker dans une variable de type:Il y a quelques situations dans lesquelles vous devez recevoir un paramètre par référence comme un
void*
, puis le jeter. Le seul que j'ai pu croiser plus souvent dans le monde réel est un fil de la procédure. Donc, vous pourriez écrire quelque chose comme:Si vous voulez vivre dangereusement, vous pouvez passer une
uintptr_t
valeur de fonte àvoid*
et de le jeter en arrière, mais attention au piège des représentations.OriginalL'auteur Davislor
printf("result = %d\n", (int)res);
est l'impression de la valeur de res (un pointeur) comme un nombre.Rappelez-vous qu'un pointeur est une adresse en mémoire, ce qui permettra d'imprimer certains aléatoire de 32 bits en nombre.
Si vous voulez imprimer la valeur stockée à cette adresse, alors vous avez besoin (int)*res - bien que l' (int) est inutile.
edit: si vous voulez imprimer la valeur (c'est à dire l'adresse) d'un pointeur, alors vous devriez utiliser
%p
c'est essentiellement le même, mais les formats de mieux et comprend si la taille d'un int et un poitner sont différentes sur votre plate-formeOriginalL'auteur Martin Beckett
Si vous avez un pointeur void
ptr
que vous connaissez des points à unint
, afin d'accéder à cetteint
écrire:C'est, d'abord le convertir en un pointeur de type int, avec opérateur de cast
(int*)
et puis déréférencement d'elle pour obtenir de la pointe-de valeur.Vous lancez le pointeur directement à un type de valeur, et bien que le compilateur sera heureux de le faire, c'est probablement pas ce que vous voulez.
OriginalL'auteur rodrigo
un est un int, mais pas un ptr, peut-être qu'il devrait être:
n'ai pas très bien comprendre votre question. Généralement parlant, le void* pointeur peut pointer vers n'importe quel type. n'avez pas besoin d'une conversion de type explicite.
OriginalL'auteur zchenah
De la taille d'un pointeur void est connu; c'est la taille d'une adresse, donc, de la même taille que tout autre pointeur. Vous êtes libre de conversion entre un entier et un pointeur, et c'est dangereux. Si tu veux prendre l'adresse de la variable
a
, vous avez besoin de convertir, à son adresse, à unvoid *
avec(void *)&a
.OriginalL'auteur mkb