Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

cast de pointeur *, ** différence ?

114 réponses
Avatar
Nico
salut,

j'ai un petit code qui m'étonne... soit une fonction prenant un void*
en paramètre, lors de son appel, si je lui passe un double*, mon
compilateur dit rien... ok.
soit une fonction retournant un void *, lorsque j'assigne un double*
avec le retour de cette fonction, mon compilateur ne dit rien...

ici donc, pas besoin de caster ni le paramètre (en (void*)), ni le
retour de fonction (en (double*))...

maintenant, on prend les même et on recommence, à la différence près
que mon argument n'est plus un void* mais un void**, et mon retour
n'est plus un void* mais aussi un void **. là plus rien ne passe...
lors de l'appel de la fonction je suis obligé de caster mon double** en
void**, et lors du retour, je suis obligé de caster en double**,
pourquoi ?

pour un exemple plus parlant, considérez le code suivant :

void *
vect_new(size_t len, size_t size_type)
{
void *v = malloc(len * size_type);
return v;
}


void
vect_free(void *vect)
{
if(vect) free(vect);
}

/*declaration du vecteur...
pas besoin de faire un cast (double*)*/

double *vect = vect_new(3,sizeof(double));

/*appel sans probleme a la compilation :
pas besoin de faire (void*)vect*/
vect_free(vect);


et maintenant avec des void** :

void **
mat_new(unsigned int nrow, unsigned int ncol, size_t size_type)
{
int i,j;
void **m = malloc(nrow * size_type);
if(m)
{
for(i=0; i<nrow; i++)
{
m[i] = malloc(ncol * size_type);
if(!m[i])
{
for(j=0; j<=i; j++)
free(m[i]);
free(m);
m = NULL;
}
}
}
return m;
}

void
mat_free(void **m,unsigned int nrow)
{
int i;
if(m)
{
for(i=0; i<nrow; i++)
if(m[i])
free(m[i]);
free(m);
}
}

/*declaration de la matrice*/
double **matrice = (double**)mat_new(4,3,sizeof(double));

/*appel sans probleme a la compilation : */
mat_free((void**)matrice,4);

là si je cast pas l'un et l'autre... warning... où se situe la
différence avec le 1er exemple ?

merci de m'éclairer à ce propos.

--
Nico,
http://astrosurf.com/nicoastro
http://nicolas.aunai.free.fr

10 réponses

Avatar
kUfa.scoopex
void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code qui

compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?
sizeof(void*)==sizeof(double*)==sizeof(truc*)

/David

-- Before C++ we had to code all of bugs by hand; now we inherit them.


Avatar
Marc Boyer
In article , kUfa.scoopex wrote:
void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code qui

compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?
sizeof(void*)==sizeof(double*)==sizeof(truc*)


Je vous invite à lire la discussion "taille d'un pointeur".

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Jean-Marc Bourguet
"kUfa.scoopex" writes:

void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code qui

compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?


Depuis toujours.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

| > Non, cela n'initialise pas les champs, mais met tous les bits à 0. En
| > particulier pour les flottants (float, double, ...) et les pointeurs, il
| > n'y a aucune garantie que cela corresponde à des valeurs nulles.
|
| Les initialiser à all-bit-zero, c'est toujours mieux que de les laisser à
| garbage.

ce n'est pas une meilleure stupidité -- c'est juste une autre
stupidité -- car...

| Quant aux flottants, s'ils sont IEEE, 0 = all-bits-zero.

Bah non. Le format IEEE-756 n'est qu'un modèle mathématique et non une
exigence hardware. Le comité C a fait la même bêtise avant de se
rattraper.

| Mais bien sûr on peut trouver des archi exotiques.

Je suppose que tu appelles « exotique », ce qui n'est pas encore
rentré dans ta connaissance/culture -- dont l'étendue soulève des
questions ;-)

[...]

| Je préfère une méthode imparfaite qui évite des problèmes qu'un
| champ de mines tout juste mentionné sur une doc.

On attend impatiemment tes tranformations en méthodes imparfaites pour
la norme C.

-- Gaby
Avatar
kUfa.scoopex
void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code

qui
compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?


Depuis toujours.


Tu veux dire qu'un pointeur peut avoir differentes tailles? Pour moi ca n'a
aucun sens. Ca voudrait dire que ce code peut etre invalide:

int *tesd;
void *temp = malloc( sizeof(int) );
test = (int*) temp;

Wow.. Impressionant..
Auriez vous un lien ou une reference que je peux examiner?

/David

-- Before C++ we had to code all of bugs by hand; now we inherit them.




Avatar
Marc Boyer
In article , kUfa.scoopex wrote:
void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code

qui
compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?


Depuis toujours.


Tu veux dire qu'un pointeur peut avoir differentes tailles? Pour moi ca n'a
aucun sens. Ca voudrait dire que ce code peut etre invalide:

int *tesd;
void *temp = malloc( sizeof(int) );
test = (int*) temp;


Non, car ici le compilateur peut faire les conversions de taille.
Prenons un autre exemple:
signed char c= 0;
double d= (double) c;
c= (signed char) d;

Les types sont de taille différentes mais les affectations
ici se font bien.

Auriez vous un lien ou une reference que je peux examiner?


Ben, encore une fois, la discussion "taille des pointeurs"
initiée par Mouarf.

-- Before C++ we had to code all of bugs by hand; now we inherit them.


Attention, c'est dangeureux de se moquer comme ça.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.





Avatar
Jean-Marc Bourguet
"kUfa.scoopex" writes:

void* est un cas particulier. Il faut un cast pour les
autres. Note que ça peut être dangereux dans les cas où
double* n'a pas la même taille que void*.
C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code

qui
compte là dessus...


Pardon?? Depuis quand peut on avoir des differents size_ptr?


Depuis toujours.


Tu veux dire qu'un pointeur peut avoir differentes tailles? Pour moi ca n'a
aucun sens. Ca voudrait dire que ce code peut etre invalide:


Non. Il y a une conversion qui peut changer la representation.

int *tesd;
void *temp = malloc( sizeof(int) );
test = (int*) temp;


tesd je suppose?

Wow.. Impressionant..
Auriez vous un lien ou une reference que je peux examiner?


ISO/IEC 9899:1999 (E)

6.2.6 et 6.3.2.3 devrait suffire. C'etait aussi vrai avant mais j'ai
pas de refs sous la main. Voir aussi les archives du groupe, c'est un
sujet qui revient...

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org





Avatar
Gabriel Dos Reis
"kUfa.scoopex" writes:

| >> >> void* est un cas particulier. Il faut un cast pour les
| >> >> autres. Note que ça peut être dangereux dans les cas où
| >> >> double* n'a pas la même taille que void*.
| >> > C'est possible ça? Si c'est vrai, ça remet en cause beaucoup de code
| >> > qui
| >> > compte là dessus...
| >>
| >> Pardon?? Depuis quand peut on avoir des differents size_ptr?
| >
| > Depuis toujours.
|
| Tu veux dire qu'un pointeur peut avoir differentes tailles? Pour moi ca n'a
| aucun sens.

Il veut dire qu'un pointeur de type « double* » n'est pas forcément de
la même taille qu'un pointeur de type « void* ». Et cela a toujours
été le cas ; et aucun changement n'a apporté lors du dernier lifting.

| Ca voudrait dire que ce code peut etre invalide:
|
| int *tesd;
| void *temp = malloc( sizeof(int) );
| test = (int*) temp;

Non, cela ne veut pas dire ça. Le cast est une requête de conversion
et le compilateur est prié d'insérer le bout de code nécessaire.

Ce dont on parle, c'est une re-interprétation douteuse des bits qui
font un double* en void*.

Entre parenthèse, le langage que tu mentionnes dans ta
signature a introduit un mot-clé exprès pouor aider le programmeur à
marquer ces constructions -- cela ne veut pas dire que son utilisation
dans ce contexte est plus juste, elle serait tout aussi fausse.

| Wow.. Impressionant..
| Auriez vous un lien ou une reference que je peux examiner?

La norme C, toute édition.

Et bonne lecture.

-- Gaby
Avatar
kUfa.scoopex
Tu veux dire qu'un pointeur peut avoir differentes tailles? Pour moi ca
n'a
aucun sens. Ca voudrait dire que ce code peut etre invalide:
Non. Il y a une conversion qui peut changer la representation.



Hmm ok, je suis bete de ne pas y avoir penser, du coup ca prends bcp plus de
sens.

int *tesd;
void *temp = malloc( sizeof(int) );
test = (int*) temp;
tesd je suppose?



Oui typo, desole.

Auriez vous un lien ou une reference que je peux examiner?
ISO/IEC 9899:1999 (E)

6.2.6 et 6.3.2.3 devrait suffire. C'etait aussi vrai avant mais j'ai
pas de refs sous la main. Voir aussi les archives du groupe, c'est un
sujet qui revient...


Ok merci pour l'info!

Ben, encore une fois, la discussion "taille des pointeurs"
initiée par Mouarf.
Je viens de le voir, merci.


-- Before C++ we had to code all of bugs by hand; now we inherit them.
Attention, c'est dangeureux de se moquer comme ça.


:)

/David

-- Before C++ we had to code all of bugs by hand; now we inherit them.


Avatar
Antoine Leca
En , Gabriel Dos Reis va escriure:
double** n'est pas censé avoir la même tailler que void**.


Certes, mais je doute que tu trouves facilement un cas où cela soit un
problème concret.

Idem pour void(**)() par rapport à void**.


Antoine