OVH Cloud OVH Cloud

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
Horst Kraemer
Yves ROMAN wrote:


Emmanuel Delahaye writes:

Jean-Marc Bourguet wrote on 08/11/04 :

Quoi que void* n'ait pas la meme taille que double*? Oui.


alors

double *p = malloc (sizeof *p * 12);

ne fonctionne pas ?


Je ne vois pas pourquoi. La seule contrainte c'est que
void* est capable de représenter précisément tous les types
de pointeurs.



Peut on donc dire, pour tout type de donnée T, que :
sizeof(void *) >= sizeof(T *) ?

Et un void * peut-il aussi contenir un pointeur de fonction ?


NON. Pour ce cas il y a (ou plutot avait) des exemples quotidiens.
Microsoft 16-bit DOS Modèle MEDIUM
pointeurs de données: 16 bit ,pointeurs de fonction: 32 bit.
Il s'agit bien d'un modèle conforme à la norme.

--
Horst




Avatar
Jean-Marc Bourguet
"Stephane Legras-Decussy" writes:

Gabriel Dos Reis a écrit dans le message :

| C'est possible, mais c'est hors-sujet. Je parle de void* et non de
| void**. Est-ce que la taille d'un double * peut être différente de
| celle d'un void * ?

Oui.

| Si c'est vrai, malloc() ne fonctionne pas.

Quelle est la chaîne logique d'inférences qui t'amène à cette
conclusion ?


euh, perso je comprend *rien* à ce fil...

quelqu'un peut expliquer le probleme comme pour un gamin
de 5 ans ?


On est parti sur des considérations beaucoup plus exotiques
que les tributs parlant l'Ewe... enfin pour autant que
"tribut" soit le mot correct pour décrire la structure
sociale en question.

La norme offre peu de garantie sur les pointeurs:

- un void* et un char* ont la même représentation
- un void* est capable de contenir toute l'information de
localisation d'un pointeur quel qu'il soit (càd T* -> void*
-> T* est la fonction identité)
- les représentations des pointeurs vers des structs sont
les mêmes quelles que soit les struct.

Il a existé des cas ou sizeof(char*) était plus grand que
sizeof(int*).

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
Jean-Marc Bourguet
Emmanuel Delahaye writes:

Gabriel Dos Reis wrote on 09/11/04 :
Je crois qu'il y a des indications dans la norme qu'on peut déduire
sizeof (void*) == sizeof (char*) && sizeof (void*) >= sizeof (T*)

parce que void* doit pouvoir contenir des pointeurs sur n'importe quel
objet. Je crois également que C99 demande


Ah, voilà qui est plus clair. Ca veux dire que pour allouer un tableau de
pointeurs générique, on doit faire

void *a = malloc (sizeof *a *taille)


Ça compile pas. *a est d'un type non complet.

On ne peut pas allouer un tableau de pointeurs sans savoir
vers quoi ces pointeurs pointent. Si c'est des

Un tel tableau est alors capable de recevoir les adresses de n'importe quel
objet. On est bien d'accord ?

sizeof (*S) == sizeof (T*), forall tags S, T.


J'ai rien compris. Pas assez neurones...


La norme containt en pratique les pointeurs vers des
structures et les unions (et les enums?, j'ai pas été
vérifié) à avoir la même représentation.

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
Charlie Gordon
Juste un point de style :

void *a = malloc (sizeof *a *taille)


C'est pas particulièrement lisible ;-)
Mais on peut faire pire : appeler le parametre de taille feozis
et rajouter un peu de sel :

#define collam
malloc(sizeof * a * feosiz)collam

comme ça on 'a' est bien mis en valeur, et risque plus de s'échapper.

Chqrlie.

PS: je mets toujours des () pour l'opérateur unaire sizeof. C'est pas
nécessaire, mais c'est un choix.

Avatar
Emmanuel Delahaye
Jean-Marc Bourguet wrote on 09/11/04 :
Ah, voilà qui est plus clair. Ca veux dire que pour allouer un tableau de
pointeurs générique, on doit faire

void *a = malloc (sizeof *a * taille)


Ça compile pas. *a est d'un type non complet.


Ok.

void *a = malloc (sizeof (void*) * taille)

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"


Avatar
Emmanuel Delahaye
Charlie Gordon wrote on 09/11/04 :
Juste un point de style :

void *a = malloc (sizeof *a *taille)


C'est pas particulièrement lisible ;-)


C'est surtout faux.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"


Avatar
Jean-Marc Bourguet
Emmanuel Delahaye writes:

Jean-Marc Bourguet wrote on 09/11/04 :
Ah, voilà qui est plus clair. Ca veux dire que pour allouer un tableau de
pointeurs générique, on doit faire
void *a = malloc (sizeof *a * taille)


Ça compile pas. *a est d'un type non complet.


Ok.

void *a = malloc (sizeof (void*) * taille)


On m'a l'air reparti pour un tour.

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
Marc Boyer
Gabriel Dos Reis wrote:
Marc Boyer writes:
| Gabriel Dos Reis wrote:
| > Je crois qu'il y a des indications dans la norme qu'on peut déduire
| >
| > sizeof (void*) == sizeof (char*)
|
| 6.2.5/26
| A pointer to void shall have the same representation and alignment
| requirements as a pointer to a character type.
|
| > && sizeof (void*) >= sizeof (T*)
|
| Ca, j'ai pas vu.

Tu peux caster T* en void* sans perte d'information.


Ca j'ai vu. Ce que je voulais dire, c'est qu'on peut faire
un compilateur conforme qui s'amuse à ajouter du padding inutile
sur T* et pas sur void*.
Bon, oui, c'est juste pour le plaisir d'imaginer
des choses conformes mais sans intérêt.

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
Antoine Leca
En , Jean-Marc Bourguet va escriure:
On est parti sur des considérations beaucoup plus exotiques
que les tributs parlant l'Ewe... enfin pour autant que
"tribut" soit le mot correct pour décrire la structure
sociale en question.


Pense pas. :-)
« Tribut » est ce que tu payes à l'État (enfin, surtout Chqrly).
Tu veux parler des tribus parlant éwé.



- un void* est capable de contenir toute l'information de
localisation d'un pointeur quel qu'il soit (càd T* -> void*
-> T* est la fonction identité)


Compare equal. Pas tout-à-fait l'identité. Pour reprendre ton exemple, la
deuxième conversion peut mettre dans ton champ caché de tag un truc
générique, la fonction de comparaison de pointeur peut ne pas tenir compte
du tag, et cela reste conforme.


Je ne sais pas comment on dit tétracapillotracteur en éwé ;-)


Antoine

Avatar
Laurent Deniau
Antoine Leca wrote:
En , Jean-Marc Bourguet va escriure:
Je ne sais pas comment on dit tétracapillotracteur en éwé ;-)


pryz2ksk ?

a+, ld.