J'ai des problèmes avec void *. Comment dois-je faire pour utiliser cette fonction clean_buffer pour les tableaux int et float.
void clean_buffer( void *ptr, int n)
{
for( int i = 0; i < n; i++)
ptr[i]=0;
}
int main(void)
{
float *pf;
int *pi;
pf = (float *) malloc(10*sizeof(float));
pi = (int *)malloc(10*sizeof(int));
clean_buffer( (float *)pf, 10);
clean_buffer( (int *)pi, 10);
return 0;
}
6 Réponses :
Vous lancez ptr dans le type approprié afin qu'il puisse être déréférencé pour effacer ce sur quoi il pointe; quelque chose que vous connaissez pointe vers un type dont vous souhaitez effacer les éléments i .
void est une valeur non que vous ne pouvez pas utiliser * ((void *) x) = v; et utiliser un cast à utiliser un pointeur vers un autre type est dangereux car la taille peut ne pas être la même
Mais, dans votre cas, vous définissez sur 0, vous pouvez donc utiliser memset ou remplacer le malloc mon calloc et il est inutile d'avoir clean_buffer :
int main(void)
{
float *pf;
int *pi;
pf = calloc(10, sizeof(float));
pi = calloc(10, sizeof(int));
return 0;
}
clean_buffer () n'est pas toujours inutile. Un bloc qui se termine par {void * p; ... memset (p, 0, 10); } est soumis à l'optimisation en abandonnant l'appel memset () . Le clean_buffer () peut être là pour nettoyer la mémoire du point de vue de la sécurité. Il est probable que volatile soit également appliqué pour éviter son optimisation.
@chux Dans le cas actuel, calloc est certainement le meilleur moyen ;-)
Le message d'OP n'est pas certain que l'utilisation de clean_buffer () est uniquement pour la première affectation. clean_buffer (p, n) peut être appelé pendant toute la durée de vie de p .
calloc () est bon et préférable si l'objectif est uniquement l'initialisation à 0, considérez pf = calloc (10, sizeof * pf); comme plus facile à coder correctement, examinez et maintenir.
Le type void n'a pas de taille. Par conséquent, vous ne pouvez pas utiliser void * pour effacer un tableau.
Vous ne pouvez pas déréférencer ce type pour la même raison.
Vous devez effectuer un cast vers un pointeur avec un type spécifique:
int main(void)
{
float *pf;
int *pi;
pf = malloc(10*sizeof(float));
pi = malloc(10*sizeof(int));
clean_buffer( pf, 10*sizeof(float));
clean_buffer( pi, 10*sizeof(int));
return 0;
}
Vous devez veiller à ce que la taille transmise à votre La fonction ne peut pas être le nombre ou les tableaux car le compilateur ne peut pas faire d'arithmétique de pointeur avec des pointeurs void * .
Et pour les tailles, vous devez utiliser size_t
Au lieu de cela, vous devez passer la taille du tableau en octets:
void clean_buffer(void *ptr, size_t n)
{
unsigned char *my_ptr = ptr;
for (int i = 0; i < n; i++)
my_ptr[i]=0;
}
Ou vous devez transmettre toute autre information pouvant être utilisée pour déterminer le type et / ou la taille des données.
Aussi:
Le cast de la valeur de retour de malloc n'est pas nécessaire en C.
Le cast des paramètres de clean_buffer vers un type que la variable a déjà, est inutile. Le type de pointeur est de toute façon converti en void * car c'est ce que la fonction attend.
Remarque:
D'autres réponses et commentaires mentionnent que vous pouvez simplement passer le pointeur vers memset ou utiliser calloc etc.
Cela peut être vrai pour ce cas très spécifique, mais si vous voulez faire autre chose que simplement remettre à zéro la mémoire, les mêmes aspects concernant les pointeurs void * s'appliquent comme je l'ai montré ici. Et dans ces cas, memset ou calloc ne sont d'aucune utilité.
void clean_buffer (void * ptr, int n)
Cette fonction requiert un void * comme paramètre.
clean_buffer ((float *) pf, 10);
Ici, vous lancez vers un pointeur flottant. Donc, c'est un type différent comme demandé
De plus, void n'a pas de taille, donc vous ne pouvez pas vraiment utiliser [] sur ptr
malloc lui-même renvoie un pointeur vide car il ne sait pas vraiment pour quel type vous allouez de la mémoire. Donc, vous devez utiliser la même taille que celle que vous passez à malloc pour effacer également le tampon.
Vous pouvez utiliser memset et transmettre la taille du tampon entier pour l'effacer sans avoir à vous soucier de son type.
void clean_buffer( void *ptr, size_t n)
{
memset(ptr, 0, n)
}
int main(void)
{
float *pf;
int *pi;
pf = (float *) malloc(10*sizeof(float));
pi = (int *)malloc(10*sizeof(int));
clean_buffer(pf, 10*sizeof(float));
clean_buffer(pi, 10*sizeof(int));
return 0;
}
De plus, comme d'autres l'ont suggéré, vous pouvez utiliser calloc si cela vous convient.
J'ai des problèmes avec void *. Comment dois-je faire pour utiliser cette fonction clean_buffer pour les tableaux int et float (?)
D'autres ont mentionné des choses utiles comme la nécessité de
sizeofpour trouver la taille, le cast non nécessaire et des alternatives pour utilisercalloc ()pour une allocation de mémoire initialisée à zéro./ p>
Pour ajouter:
sizeof * object_pointer
Utilisez
sizeof * object_pointerpour trouver le Taille. Il est moins sujet aux erreurs, plus facile à examiner et à maintenir que le codage dans le type.void clean_buffer(void *ptr, size_t n) { volatile unsigned char *vuc = ptr; for(size_t i = 0; i < n; i++) vuc[i]=0; } }volatile
Nettoyage de la mémoire après son utilisation finale a tendance à être optimisée et donc une bonne raison de ne pas utiliser
memset ()lorsque la sécurité de la mémoire est préoccupante. Utilisez plutôtvolatilepour éviter queclean_buffer ()ne soit lui-même optimisé.// clean_buffer( (float *)pf, 10); // clean_buffer( (int *)pi, 10); // cast not needed clean_buffer(pf, sizeof *pf * 10); // No need to mention type! clean_buffer(pi, sizeof *pi * 10);
Êtes-vous sûr de ne pas vouloir utiliser memset au lieu de clean_buffer? La norme IEEE 754 garantit que la remise à zéro d'un tampon flottant définira les valeurs sur 0,0f.
Vous pouvez plutôt transmettre la taille du tampon en octets . Mais à ce stade, vous écrivez un
memsetmoins efficace. Alors utilisez simplement ça .Vous n'avez jamais besoin de convertir quoi que ce soit dans son propre type, comme dans
(float *) pf.De plus, votre objectif est-il ici de mettre à zéro les tampons immédiatement après leur attribution? Si tel est le cas, vous pouvez utiliser calloc qui initialise la mémoire à zéro pour vous.
@SirDarius D'après le titre, il semble qu'il s'agisse de l'utilisation des pointeurs
void *en général, l'extrait de code n'étant qu'un MCVE à titre d'illustration.@Gerhardh alors que le titre est générique, la question elle-même est assez spécifique, et borde un problème X-Y (poser une question sur une solution, et non sur le problème à résoudre, c'est-à-dire. Mes questions demandent des éclaircissements à OP pour s'assurer que c'est bien le cas.