Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interchangeabilité des types pointeur

37 views
Skip to first unread message

Jérôme Frgacic

unread,
Jan 7, 2013, 10:43:42 AM1/7/13
to
Bonjour à tous,

Tout d'abord, meilleurs vœux pour cette année 2013.

Dans le cas d'un petit projet personnel, je souhaite crée une liste dont chaque nœud comporte un pointeur vers une ressource allouée et un pointeur de fonction spécifiant la fonction permettant de libérer cette ressource. Ainsi, j'ai représenté un nœud à l'aide de cette structure :

struct ressource {
void *data;
void (*delete)();
struct ressource * next;
};

Le problème, c'est que les ressources allouées sont stockées au sein d'un pointeur générique (pointeur sur void), mais que les fonctions de destructions référencées, elles, n'attendent pas forcément un tel pointeur (parfois oui, comme free, mais parfois non, comme fclose ou autre). Je sais que, à ce sujet, la norme fourni quelques garanties pour certains types de pointeurs :

C11 (n1570), § 6.2.5 Types, al. 28, p. 43
> A pointer to void shall have the same representation and alignment
> requirements as a pointer to a character type. Similarly, pointers
> to qualified or unqualified versions of compatible types shall have
> the same representation and alignment requirements. All pointers to
> structure types shall have the same representation and alignment
> requirements as each other. All pointers to union types shall have the
> same representation and alignment requirements as each other. Pointers
> to other types need not have the same representation or alignment
> requirements.

mais pour le reste, rien n'est prévu. Aussi, j'aurais voulu savoir si j'ai des chances de tomber sur des architectures où une telle solution pose problème et, également, s'il existe une autre solution, cette fois-ci portable ?

Merci d'avance pour vos réponses.

Marc Espie

unread,
Jan 7, 2013, 10:59:13 AM1/7/13
to
In article <648b4e38-2f03-4eee...@googlegroups.com>,
J�r�me Frgacic <jerome....@yahoo.fr> wrote:
>Bonjour � tous,
>
>Tout d'abord, meilleurs v�ux pour cette ann�e 2013.
>
>Dans le cas d'un petit projet personnel, je souhaite cr�e une liste dont
>chaque n�ud comporte un pointeur vers une ressource allou�e et un
>pointeur de fonction sp�cifiant la fonction permettant de lib�rer cette
>ressource. Ainsi, j'ai repr�sent� un n�ud � l'aide de cette structure :
>
>struct ressource {
> void *data;
> void (*delete)();
> struct ressource * next;
>};
>
>Le probl�me, c'est que les ressources allou�es sont stock�es au sein
>d'un pointeur g�n�rique (pointeur sur void), mais que les fonctions de
>destructions r�f�renc�es, elles, n'attendent pas forc�ment un tel
>pointeur (parfois oui, comme free, mais parfois non, comme fclose ou
>autre). Je sais que, � ce sujet, la norme fourni quelques garanties pour
>certains types de pointeurs :
>
>C11 (n1570), � 6.2.5 Types, al. 28, p. 43
>> A pointer to void shall have the same representation and alignment
>> requirements as a pointer to a character type. Similarly, pointers
>> to qualified or unqualified versions of compatible types shall have
>> the same representation and alignment requirements. All pointers to
>> structure types shall have the same representation and alignment
>> requirements as each other. All pointers to union types shall have the
>> same representation and alignment requirements as each other. Pointers
>> to other types need not have the same representation or alignment
>> requirements.
>
>mais pour le reste, rien n'est pr�vu. Aussi, j'aurais voulu savoir si
>j'ai des chances de tomber sur des architectures o� une telle solution
>pose probl�me et, �galement, s'il existe une autre solution, cette
>fois-ci portable ?

Il ne reste pas grand chose dans "le reste"... ca couvre les pointeurs
de fonction, en fait. C'est le cas un peu bizarre en C, mais tant que
tu ne manipules que des pointeurs sur autre chose que du code, tout
ceci est tres portable.

Pour le reste, cote cast entre pointeurs, tu peux avoir des problemes
d'aliasing si tu ne passes pas un des types etiquette comme "pointeur
generique", c'est-a-dire void*, char* et assimiles. Donc dans ton cas,
zero probleme.

Antoine Leca

unread,
Jan 8, 2013, 4:13:42 AM1/8/13
to
J�r�me Frgacic �crivit :
> Le probl�me, c'est que les ressources allou�es sont stock�es au sein d'un
> pointeur g�n�rique (pointeur sur void), mais que les fonctions de
> destructions r�f�renc�es, elles, n'attendent pas forc�ment un tel pointeur
> (parfois oui, comme free, mais parfois non, comme fclose ou autre). Je
> sais que, � ce sujet, la norme fourni quelques garanties pour certains
> types de pointeurs :
>
> C11 (n1570), � 6.2.5 Types, al. 28, p. 43
[couic]
>
> mais pour le reste, rien n'est pr�vu.

Euh, si. 6.3 /Conversions/, � 6.3.2.3 /Pointers/, al. 1 :
A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to
a pointer to void and back again; the result shall compare
equal to the original pointer.

En gros, tant que ton code manipule des pointeurs g�n�riques et que
derri�re il y a des pointeurs vers des types _objets_, tout va bien.
Il faut bien comprendre que si dans ton code tu �cris
FILE* f;
ptr_ress->data = f;
il y a conversion de FILE* � void* ; et quand tu �cris plus tard
fclose( (FILE*)(ptr_ress->data) );
la conversion de retour (/back/) est m�me explicite !


En r�gle g�n�rale les repr�sentations et les alignements sont bien
entendu identiques ; mais dans les cas o� il y a des diff�rences (genre
des pointeurs vers char sur 48 bits quand un pointeur vers struct est
sur 32 bits; ou les pointeurs _far* ou _segment* qui firent la joie des
programmeurs PC des ann�es 1985-1990...), c'est le probl�me du
compilateur, pas celui de la norme, ni du programmeur qui la suit.


Antoine

Marc Espie

unread,
Jan 8, 2013, 5:04:43 AM1/8/13
to
In article <kcgo07$shm$1...@shakotay.alphanet.ch>,
Antoine Leca <ro...@localhost.invalid> wrote:
> FILE* f;
> ptr_ress->data = f;
>il y a conversion de FILE* � void* ; et quand tu �cris plus tard
> fclose( (FILE*)(ptr_ress->data) );
>la conversion de retour (/back/) est m�me explicite !

En C, tu n'as pas besoin de la conversion de retour. J'aurais meme tendance
a dire qu'elle est nefaste, puisqu'elle peut masquer une erreur si ton
type de depart n'est pas un pointeur.

Je sais que c'est sans doute une mauvaise habitude heritee du C++, ou meme
une envie de faire dans la compatibilite gratuite.

J'aurais bien envie de dire que si vraiment tu veux la compatibilite,
ca vaut le coup de cacher ca derriere une macro:

#ifdef __cplusplus
#define voidp_cast(T, v) reinterpret_cast<T>(v)
#else
#define voidp_cast(T, v) (v)
#endif

fclose(voidp_cast(FILE *, ptr_ress->data));

Jean-Marc Bourguet

unread,
Jan 8, 2013, 7:40:50 AM1/8/13
to
es...@lain.home (Marc Espie) writes:

> Je sais que c'est sans doute une mauvaise habitude heritee du C++, ou meme
> une envie de faire dans la compatibilite gratuite.

Ou simplement l'idee que c'est plus logique de marquer les conversions
non sures ;)

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Marc Espie

unread,
Jan 8, 2013, 11:21:40 AM1/8/13
to
In article <pxbtxqr...@bourguet.org>,
Jean-Marc Bourguet <j...@bourguet.org> wrote:
>es...@lain.home (Marc Espie) writes:
>
>> Je sais que c'est sans doute une mauvaise habitude heritee du C++, ou meme
>> une envie de faire dans la compatibilite gratuite.
>
>Ou simplement l'idee que c'est plus logique de marquer les conversions
>non sures ;)

... mais plus dangereux, puisque ton compilo acceptera aussi bien.

void *p;
struct a *q;
q = (struct a *)p;


que
int p;
struct a *q;
q = (struct a *)p;


...

Jérôme Frgacic

unread,
Jan 8, 2013, 11:28:39 AM1/8/13
to
Antoine Leca a écrit :
> Euh, si. 6.3 /Conversions/, § 6.3.2.3 /Pointers/, al. 1 :
> A pointer to void may be converted to or from a pointer to any
> object type. A pointer to any object type may be converted to
> a pointer to void and back again; the result shall compare
> equal to the original pointer.
>
> En gros, tant que ton code manipule des pointeurs génériques et que
> derrière il y a des pointeurs vers des types _objets_, tout va bien.
> Il faut bien comprendre que si dans ton code tu écris
> FILE* f;
> ptr_ress‐>data = f;
> il y a conversion de FILE* à void* ; et quand tu écris plus tard
> fclose( (FILE*)(ptr_ress‐>data) );
> la conversion de retour (/back/) est même explicite !

En fait, mon problème est que la libération de la ressource est faite
via le pointeur de fonction « delete » de la structure. Autrement dit,
pour chaque ressource, on a un appel du type :

ptr_ress‐>delete(ptr_ress‐>data);

Or, si cela ne pose pas de problème quand la fonction référencée est
free, c’est plus gênant s’il s’agit de fclose car elle reçoit un objet
de type « pointeur sur void » alors qu’elle attend un objet de type «
pointeur sur structure ».

Je me demande donc si une telle technique pose, de manière générale,
un problème (appremment non) et s’il n’existe pas une alternative qui
ne pose pas de problèmes de portabilité.

Marc Espie a écrit :
> Il ne reste pas grand chose dans "le reste"... ca couvre les pointeurs
> de fonction, en fait. C’est le cas un peu bizarre en C, mais tant que
> tu ne manipules que des pointeurs sur autre chose que du code, tout
> ceci est tres portable.

Ben, disons que, en théorie, il reste : les pointeurs sur tous les
types natifs (sauf void et char), les pointeurs de pointeur, les
pointeurs sur tableau et les pointeurs de fonction.

Mais, si je comprend bien, dans la réalité, tous les pointeurs ont
généralement la même taille sauf les pointeurs de fonctions ?

Marc Espie

unread,
Jan 8, 2013, 11:52:26 AM1/8/13
to
In article <f0690b58-7b81-4a56...@googlegroups.com>,
J�r�me Frgacic <jerome....@yahoo.fr> wrote:
>Marc Espie a écrit :
>> Il ne reste pas grand chose dans "le reste"... ca couvre les pointeurs
>> de fonction, en fait. C’est le cas un peu bizarre en C, mais tant que
>> tu ne manipules que des pointeurs sur autre chose que du code, tout
>> ceci est tres portable.
>
>Ben, disons que, en théorie, il reste : les pointeurs sur tous les
>types natifs (sauf void et char), les pointeurs de pointeur, les
>pointeurs sur tableau et les pointeurs de fonction.

Non, il faut que tu relises attentivement ce que la norme appelle un objet
dans ce contexte precis.

Ca couvre tout sauf les pointeurs de fonction...

Jérôme Frgacic

unread,
Jan 8, 2013, 12:51:23 PM1/8/13
to es...@nerim.net
> Non, il faut que tu relises attentivement ce que la norme appelle un
> objet dans ce contexte precis.
>
> Ca couvre tout sauf les pointeurs de fonction...

J’avoue que je suis un peu perdu là... Lorsque je lis ce passage :

> A pointer to void shall have the same representation and alignment
> requirements as a pointer to a character type. Similarly, pointers to
> qualified or unqualified versions of compatible types shall have the
> same representation and alignment requirements. All pointers to
> structure types shall have the same representation and alignment
> requirements as each other. All pointers to union types shall have the
> same representation and alignment requirements as each other. Pointers
> to other types need not have the same representation or alignment
> requirements.

Je comprends que la norme nous garantit que, ont la même taille et le
même alignement :

‐ un pointeur sur char et un pointeur sur void ;
‐ un pointeur sur un type et un pointeur sur le même type qualifié ;
‐ un pointeur sur structure et un pointeur sur une autre structure ;
‐ un pointeur sur union et un pointeur sur une autre union.

Pour le reste, la norme ne nous dit rien, ce qui signifie, pour moi,
que rien ne me garantit qu’un pointeur sur une structure à la même
taille et le même alignement qu’un pointeur sur void et que, par
conséquent, le code suivant a un comportement indéterminé :

#include <stdio.h>

struct coord {
int x;
int y;
};

static void print_ptr();

int
main(void)
{
struct coord coord;
struct coord *p = &coord;

print_ptr(p);
return 0;
}


static void
print_ptr(void *p)
{
printf("%p\n", p);
}


me trompé‐je ?

Marc Espie

unread,
Jan 8, 2013, 1:02:46 PM1/8/13
to
In article <a90229bf-078e-4d91...@googlegroups.com>,
J�r�me Frgacic <jerome....@yahoo.fr> wrote:
>> Non, il faut que tu relises attentivement ce que la norme appelle un
>> objet dans ce contexte precis.
>>
>> Ca couvre tout sauf les pointeurs de fonction...
>
>J’avoue que je suis un peu perdu là... Lorsque je lis ce passage :
>
>> A pointer to void shall have the same representation and alignment
>> requirements as a pointer to a character type. Similarly, pointers to
>> qualified or unqualified versions of compatible types shall have the
>> same representation and alignment requirements. All pointers to
>> structure types shall have the same representation and alignment
>> requirements as each other. All pointers to union types shall have the
>> same representation and alignment requirements as each other. Pointers
>> to other types need not have the same representation or alignment
>> requirements.
>
>Je comprends que la norme nous garantit que, ont la même taille et le
>même alignement :
>
> ‐ un pointeur sur char et un pointeur sur void ;
> ‐ un pointeur sur un type et un pointeur sur le même type qualifié ;
> ‐ un pointeur sur structure et un pointeur sur une autre structure ;
> ‐ un pointeur sur union et un pointeur sur une autre union.

Tu confonds le pointeur et l'objet pointe, pour la partie alignement.

Antoine Leca

unread,
Jan 9, 2013, 5:36:41 AM1/9/13
to
Marc Espie écrivit :
> In article <kcgo07$shm$1...@shakotay.alphanet.ch>,
> Antoine Leca <ro...@localhost.invalid> wrote:
>> FILE* f;
>> ptr_ress->data = f;
>> il y a conversion de FILE* à void* ; et quand tu écris plus tard
>> fclose( (FILE*)(ptr_ress->data) );
>> la conversion de retour (/back/) est même explicite !
>
> En C, tu n'as pas besoin de la conversion de retour. J'aurais meme tendance
> a dire qu'elle est nefaste, puisqu'elle peut masquer une erreur si ton
> type de depart n'est pas un pointeur.

Très juste, cela m'avait échappé.


Antoine

Antoine Leca

unread,
Jan 9, 2013, 6:19:11 AM1/9/13
to
Jérôme Frgacic écrivit :
> Antoine Leca a écrit :
>> Euh, si. 6.3 /Conversions/, § 6.3.2.3 /Pointers/, al. 1 :
>> A pointer to void may be converted to or from a pointer to any
>> object type. A pointer to any object type may be converted to
>> a pointer to void and back again; the result shall compare
>> equal to the original pointer.
>>
>> En gros, tant que ton code manipule des pointeurs génériques et que
>> derrière il y a des pointeurs vers des types _objets_, tout va bien.
>> Il faut bien comprendre que si dans ton code tu écris
>> FILE* f;
>> ptr_ress‐>data = f;
>> il y a conversion de FILE* à void* ; et quand tu écris plus tard
>> fclose( (FILE*)(ptr_ress‐>data) );
>> la conversion de retour (/back/) est même explicite !
>
> En fait, mon problème est que la libération de la ressource est faite
> via le pointeur de fonction « delete » de la structure. Autrement dit,
> pour chaque ressource, on a un appel du type :
>
> ptr_ress‐>delete(ptr_ress‐>data);

Halte au hold-up !

Je reprend ta déclaration initiale :

struct ressource {
void *data;
void (*delete)();
struct ressource * next;
};

Le problème, c'est que tu utilises un prototype générique pour "delete"
Autrement dit, il n'y a plus aucun contrôle, tu peux tout aussi bien appeler
ptr_ress‐>delete(42);


Je croyais que ton idée, c'était d'écrire

struct ressource {
void *data;
void (*delete)(void*);
struct ressource * next;
};

et de coder les adjudants «delete», par exemple pour la mémoire
void delete_memoire(void*p) { free(p); }
ou pour les fichiers
void delete_fichier(void*f) { fclose(p); }

Cette dernière fonction va effectuer la conversion de type si besoin
est, et va aussi va permettre d'ignorer la différence de type des
valeurs de retour: la signature de &fclose est int(*)(), pas void(*)()


[couic]
> Mais, si je comprend bien, dans la réalité, tous les pointeurs ont
> généralement la même taille sauf les pointeurs de fonctions ?

Sauf machines vraiment bizarres, oui. Les exemples les plus classiques
des cas contraires sont d'une part les machines genre PDP10 ou certains
Unisys à adressage mot (donc un pointeur vers char est plus gros car il
faut y ajouter un sous-pointeur vers le byte au sein du mot), et d'autre
part les adressages «segmentés» genre iAPX286 en mode H où chaque
structure utilise son propre segment.

De plus, un problème avec les pointeurs de fonctions, au delà d'une
taille différente, ils peuvent être incommensurables, opérant dans un
espace d'adresses différent, avec un jeu d'instructions différentes.


Antoine

Jérôme Frgacic

unread,
Jan 9, 2013, 12:16:10 PM1/9/13
to
Marc Espie a écrit :
> Tu confonds le pointeur et l’objet pointe, pour la partie alignement.

Il me semble que ce passage traîte bien de l’alignement des types
pointeur et non des types pointés. En effet, si cela n’était pas le
cas, on en déduirait que toutes les structures doivent avoir le même
alignement, de même pour les unions, or ce n’est à ma connaissance pas
le cas.

Antoine Leca a écrit :
> Le problème, c’est que tu utilises un prototype générique pour
> "delete" Autrement dit, il n’y a plus aucun contrôle, tu peux tout
> aussi bien appeler
>
> ptr_ress‐>delete(42);
>

Oui, j’avais choisit ce type de pointeur pour éviter de multiples
conversions explicites et aussi pour éviter cette création «
d’adjudants ». Mais, au final, je ne me rend compte que ce n’est pas
aussi bien que cela.

Antoine Leca a écrit :
> Sauf machines vraiment bizarres, oui. Les exemples les plus classiques
> des cas contraires sont d’une part les machines genre PDP10 ou
> certains Unisys à adressage mot (donc un pointeur vers char est plus
> gros car il faut y ajouter un sous‐pointeur vers le byte au sein du
> mot), et d’autre part les adressages «segmentés» genre iAPX286 en mode
> H où chaque structure utilise son propre segment.

Ok, c’est ce dont je voulais avant tout m’assurer.
Merci pour cette précision. ;)

Jean-Marc Bourguet

unread,
Jan 10, 2013, 4:21:26 AM1/10/13
to
Jérôme Frgacic <jerome....@yahoo.fr> writes:

> Antoine Leca a écrit :
>> Sauf machines vraiment bizarres, oui. Les exemples les plus classiques
>> des cas contraires sont d’une part les machines genre PDP10 ou
>> certains Unisys à adressage mot (donc un pointeur vers char est plus
>> gros car il faut y ajouter un sous‐pointeur vers le byte au sein du
>> mot), et d’autre part les adressages «segmentés» genre iAPX286 en mode
>> H où chaque structure utilise son propre segment.
>
> Ok, c’est ce dont je voulais avant tout m’assurer.
> Merci pour cette précision. ;)

Il y a aussi le probleme des optimiseurs.

Il y a deux points de vue sur les comportements indefinis: ils sont la
pour traiter des cas particuliers et en dehors de ceux-ci il faut agir
de maniere sensee; ils sont reellement la porte ouverte a tout. Ceux
qui ecrivent les optimiseurs ont tendance a avoir le second.

Marc Espie

unread,
Jan 10, 2013, 4:59:21 AM1/10/13
to
In article <kcjjnh$ikl$1...@shakotay.alphanet.ch>,
Antoine Leca <ro...@localhost.invalid> wrote:
>Jérôme Frgacic écrivit :
>[couic]
>> Mais, si je comprend bien, dans la réalité, tous les pointeurs ont
>> généralement la même taille sauf les pointeurs de fonctions ?
>
>Sauf machines vraiment bizarres, oui. Les exemples les plus classiques
>des cas contraires sont d'une part les machines genre PDP10 ou certains
>Unisys à adressage mot (donc un pointeur vers char est plus gros car il
>faut y ajouter un sous-pointeur vers le byte au sein du mot), et d'autre
>part les adressages «segmentés» genre iAPX286 en mode H où chaque
>structure utilise son propre segment.

Attention, je crois qu'on melange deux trucs.

Jerome se demande si ce qu'il fait fonctionne avec du C standard de
facon portable.

Et les trucs dont tu parles sortent du C standard.

Plus exactement, il y a la possibilite a des implementations d'avoir
des trucs "implementation-defined" pour certains adressages (voire d'avoir
des archis suffisamment exotiques pour qu'il y ait des implementations de
C qui ne se conforment pas completement a la norme).

Mais, de ce que je sais du C, dans une implementation conforme, il n'y a pas
de souci avec les pointeurs.

Les seuls pointeurs "bizarres" sont explicites, c'est les trucs comme
__far et __near sur certaines implementations. La norme couvre ces cas,
mais tu ne vas pas te retrouver avec ceux-ci "par surprise". Tu n'es plus
dans la partie strictement conforme, tu es dans la partie
"implementation-defined", et la norme, car c'est son boulot, te dit que
tout marche bien tant que tu restes dans les clous.

Jean-Marc Bourguet

unread,
Jan 10, 2013, 7:20:47 AM1/10/13
to
es...@lain.home (Marc Espie) writes:

> In article <kcjjnh$ikl$1...@shakotay.alphanet.ch>,
> Antoine Leca <ro...@localhost.invalid> wrote:
>>Jérôme Frgacic écrivit :
>>[couic]
>>> Mais, si je comprend bien, dans la réalité, tous les pointeurs ont
>>> généralement la même taille sauf les pointeurs de fonctions ?
>>
>>Sauf machines vraiment bizarres, oui. Les exemples les plus classiques
>>des cas contraires sont d'une part les machines genre PDP10 ou certains
>>Unisys à adressage mot (donc un pointeur vers char est plus gros car il
>>faut y ajouter un sous-pointeur vers le byte au sein du mot), et d'autre
>>part les adressages «segmentés» genre iAPX286 en mode H où chaque
>>structure utilise son propre segment.
>
> Attention, je crois qu'on melange deux trucs.
>
> Jerome se demande si ce qu'il fait fonctionne avec du C standard de
> facon portable.


> Et les trucs dont tu parles sortent du C standard.

Pas d'accord: 2.6.5/28 (C 11 mais je suis sur que ce n'est pas quelque
chose de nouveau)

A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type. Similarly, pointers to
qualified or unqualified versions of compatible types shall have the
same representation and alignment requirements. All pointers to
structure types shall have the same representation and alignment
requirements as each other. All pointers to union types shall have the
same representation and alignment requirements as each other. Pointers
to other types need not have the same representation or alignment
requirements.

void* peut avoir une représentation différente de FILE*, et passer un
void* a une fonction qui s'attend a un FILE* sans prototype declanchant
une conversion implicite est un UB sur ces machines. (Ces
implementations sont annectotiques de nos jours, les rares cas modernes
dont j'ai connaissance qui sont adressables par mots choisissent d'avoir
sizeof(char)==sizeof(int)==1 plutot que d'avoir sizeof(int)>1 et
sizeof(char*)>sizeof(int*) -- de plus si j'ai bonne memoire ce n'est pas
conforme a POSIX).

Jean-Marc Bourguet

unread,
Jan 10, 2013, 7:25:17 AM1/10/13
to
Jean-Marc Bourguet <j...@bourguet.org> writes:

> void* peut avoir une représentation différente de FILE*, et passer un
> void* a une fonction qui s'attend a un FILE* sans prototype declanchant
> une conversion implicite est un UB sur ces machines.

Je me demande si le comportement est defini ou pas sur une
implementation qui choisit d'avoir la meme representation pour tous les
pointeurs; il faudrait rechercher l'ensemble des references pertinentes
et j'ai pas le souvenir de l'avoir deja fait -- pire, ca me semble
toucher a des zones ou les differences de formulation entre C90, C99 (et
peut-etre C11) ne sont pas minimes.

Antoine Leca

unread,
Jan 10, 2013, 2:23:03 PM1/10/13
to
Marc Espie �crivit :
> Attention, je crois qu'on melange deux trucs.

C'est bien possible, merci de recentrer.


> Jerome se demande si ce qu'il fait fonctionne avec du C standard de
> facon portable.

Et justement, je ne trouve que ce soit une tr�s bonne id�e.

Pour m�moire, il voudrait manipuler des fonctions prenant des types
pointeurs vari�s en param�tre, _sans_ utiliser de prototypes.

Ne pas utiliser de prototype est effectivement du C standard, mais je ne
suis pas s�r que ce soit une tr�s bonne solution pour assurer la
portabilit�.

D'un autre c�t�, en termes de perfs, je ne sais pas si les compilateurs
actuels sont assez finaux pour remplacer
void delete_memoire(void*p) { free(p); }
void delete_fichier(void*f) { fclose(p); }
par
.alias delete_memoire, free
.alias delete_fichier, fclose
et �viter l'indirection � inutile �.


Apr�s, et c'est l� que l'on m�lange, il est vrai qu'avec la
quasi-totalit� des machines actuelles, le seul effet de tout cela sera
des avertissements sans frais (m�me avec des prototypes).
Et il est bien clair que la tendance va dans le sens d'avoir de moins en
moins de ces cas particuliers, et au contraire d'avoir tous les
pointeurs (vers objets) avec des repr�sentations identiques.


De plus, un clang r�cent (3.1) proteste de la mani�re ("incompatible
pointer type") quand j'�cris du code qui va marcher � partout �, comme

int (*delete_fichier)(void*) = fclose;

ou si j'�cris du code beaucoup plus tendancieux, genre

int (*delete_memoire)() = free;
/* ... */
if( delete_memoire(&ressource) != 0 ) /* ta-da */

alors m�me que dans le second cas, l'appel ult�rieur avec utilisation de
la valeur retourn�e appelle au meurtre...


Antoine

Jérôme Frgacic

unread,
Jan 14, 2013, 2:31:03 PM1/14/13
to
Merci à tous pour vos réponses et vos explications, me voilà fixé sur cette interrogation. :)
0 new messages