OVH Cloud OVH Cloud

#define : Alias de fonctions ou de champ d'une structure ?

25 réponses
Avatar
Stephane Wirtel
bonjour à tous,

Je ne sais pas pourquoi, mais je pense avoir vu un jour un bout de code écrit en C ou C++, qui
donnait la possibilité de créer un alias d'un champ dans une structure.

Je pense que cela se basait sur #define, style:

typedef struct StructFun {
int age;
#define Age age
} StructFun;

Aurais-je rêvé ? Avez-vous déjà vu ayant une similitude avec ma description ?

Merci,

Stephane

10 réponses

1 2 3
Avatar
Marc Boyer
Le 18-10-2005, Fabien LE LEZ a écrit :
On Tue, 18 Oct 2005 15:04:00 +0200, Stephane Wirtel
:

typedef struct StructFun {


Ça, c'est sans aucun doute du C.

int age;


[SNIP]


- pour une variable, c'est plus compliqué (Peut-être peut-on faire
quelque chose avec un "union" ?), mais a priori le cas est très rare
de toute façons, puisque généralement, une variable membre est privée.


J'ai lancé la discussion sur fclc, et il semble qu'on pourrait
en effet faire

typedef struct StructFun {
union {
int age;
int Age;
};
} StructFun;

pour avoir un alias de age qui serait Age uniquement dans
la portée de StructFun.

Mais bon, ça discute ferme ;-)


Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangeureux
que prendre un boulevard dans le sens légal. À qui la faute ?


Avatar
kanze
Marc Boyer wrote:
On Tue, 18 Oct 2005 15:04:00 +0200, Stephane Wirtel
:

typedef struct StructFun {


Ça, c'est sans aucun doute du C.

int age;



[SNIP]

- pour une variable, c'est plus compliqué (Peut-être peut-on
faire quelque chose avec un "union" ?), mais a priori le cas
est très rare de toute façons, puisque généralement, une
variable membre est privée.


J'ai lancé la discussion sur fclc, et il semble qu'on
pourrait en effet faire

typedef struct StructFun {
union {
int age;
int Age;
};
} StructFun;

pour avoir un alias de age qui serait Age uniquement dans la
portée de StructFun.

Mais bon, ça discute ferme ;-)


Il faudrait que j'y jette un coup d'oeil, mais je ne sais pas ce
qu'il y a à discuter. Selon la norme, si la dernière affectation
ou initialisation est à age, tout accès à Age est un
comportement indéfini, et vice versa. Dans la pratique, c'est
une technique répandue et acceptée, au point qu'aucun
compilateur n'oserait ne pas le supporter. (Je crois, en tout
cas. G++ m'a étonné une ou deux fois dans la passée avec ce
qu'il a réfusé.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Marc Boyer
kanze a écrit :
J'ai lancé la discussion sur fclc, et il semble qu'on
pourrait en effet faire

typedef struct StructFun {
union {
int age;
int Age;
};
} StructFun;

pour avoir un alias de age qui serait Age uniquement dans la
portée de StructFun.

Mais bon, ça discute ferme ;-)


Il faudrait que j'y jette un coup d'oeil, mais je ne sais pas ce
qu'il y a à discuter. Selon la norme, si la dernière affectation
ou initialisation est à age, tout accès à Age est un
comportement indéfini, et vice versa.


Avec un bémol posé sur les structures qui commencent par
les "même" champs. Ce qui fait que les structures ont un
traitement privilégié sur les types de base.

Dans la pratique, c'est
une technique répandue et acceptée, au point qu'aucun
compilateur n'oserait ne pas le supporter. (Je crois, en tout
cas. G++ m'a étonné une ou deux fois dans la passée avec ce
qu'il a réfusé.)


Oui, dans la pratique, je suis confiant.

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangereux
que prendre un boulevard dans le sens légal. À qui la faute ?


Avatar
Gabriel Dos Reis
"kanze" writes:

[...]

| > typedef struct StructFun {
| > union {
| > int age;
| > int Age;
| > };
| > } StructFun;
|
| > pour avoir un alias de age qui serait Age uniquement dans la
| > portée de StructFun.
|
| > Mais bon, ça discute ferme ;-)
|
| Il faudrait que j'y jette un coup d'oeil, mais je ne sais pas ce
| qu'il y a à discuter. Selon la norme, si la dernière affectation
| ou initialisation est à age, tout accès à Age est un
| comportement indéfini, et vice versa. Dans la pratique, c'est
| une technique répandue et acceptée, au point qu'aucun
| compilateur n'oserait ne pas le supporter. (Je crois, en tout
| cas. G++ m'a étonné une ou deux fois dans la passée avec ce
| qu'il a réfusé.)

GCC documente que c'est un fonctionnement « normal » -- au sens qu'il
garantit la sémantique.

-- Gaby
Avatar
Gabriel Dos Reis
Marc Boyer writes:

| kanze a écrit :
| >> J'ai lancé la discussion sur fclc, et il semble qu'on
| >> pourrait en effet faire
| >
| >> typedef struct StructFun {
| >> union {
| >> int age;
| >> int Age;
| >> };
| >> } StructFun;
| >
| >> pour avoir un alias de age qui serait Age uniquement dans la
| >> portée de StructFun.
| >
| >> Mais bon, ça discute ferme ;-)
| >
| > Il faudrait que j'y jette un coup d'oeil, mais je ne sais pas ce
| > qu'il y a à discuter. Selon la norme, si la dernière affectation
| > ou initialisation est à age, tout accès à Age est un
| > comportement indéfini, et vice versa.
|
| Avec un bémol posé sur les structures qui commencent par
| les "même" champs. Ce qui fait que les structures ont un
| traitement privilégié sur les types de base.

Oui, mais c'est un peu plus compliqué que cela. Nous avions eu cette
discussion maintes fois sur la liste GCC. Regarde aussi les exemples
de la norme C.

-- Gaby
Avatar
Marc Boyer
Gabriel Dos Reis a écrit :
Marc Boyer writes:
| kanze a écrit :
| >> J'ai lancé la discussion sur fclc, et il semble qu'on
| >> pourrait en effet faire
| >
| >> typedef struct StructFun {
| >> union {
| >> int age;
| >> int Age;
| >> };
| >> } StructFun;
| >
| >> pour avoir un alias de age qui serait Age uniquement dans la
| >> portée de StructFun.
| >
| >> Mais bon, ça discute ferme ;-)
| >
| > Il faudrait que j'y jette un coup d'oeil, mais je ne sais pas ce
| > qu'il y a à discuter. Selon la norme, si la dernière affectation
| > ou initialisation est à age, tout accès à Age est un
| > comportement indéfini, et vice versa.
|
| Avec un bémol posé sur les structures qui commencent par
| les "même" champs. Ce qui fait que les structures ont un
| traitement privilégié sur les types de base.

Oui, mais c'est un peu plus compliqué que cela. Nous avions eu cette
discussion maintes fois sur la liste GCC.


La suite logique serait de te demander un critère de recherche dans
les arcgives de la liste gcc, mais je ne suis pas sur d'avoir
le courage de tout lire.

Regarde aussi les exemples de la norme C.


A part 6.5.2.3/8, je n'ai pas vu grand chose (mais je ne
suis pas un habitué des recherches dans la norme).

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangereux
que prendre un boulevard dans le sens légal. À qui la faute ?

Avatar
Gabriel Dos Reis
Marc Boyer writes:


[...]

| > Oui, mais c'est un peu plus compliqué que cela. Nous avions eu cette
| > discussion maintes fois sur la liste GCC.
|
| La suite logique serait de te demander un critère de recherche dans
| les arcgives de la liste gcc, mais je ne suis pas sur d'avoir
| le courage de tout lire.

:-)

| > Regarde aussi les exemples de la norme C.
|
| A part 6.5.2.3/8, je n'ai pas vu grand chose (mais je ne
| suis pas un habitué des recherches dans la norme).

Regarde l'exemple avec struct t1, struct t2 et l'appel à f() dans g().

-- Gaby
Avatar
Marc Boyer
Gabriel Dos Reis a écrit :
Marc Boyer writes:
| > Oui, mais c'est un peu plus compliqué que cela. Nous avions eu cette
| > discussion maintes fois sur la liste GCC.
|
| La suite logique serait de te demander un critère de recherche dans
| les arcgives de la liste gcc, mais je ne suis pas sur d'avoir
| le courage de tout lire.

:-)

| > Regarde aussi les exemples de la norme C.
|
| A part 6.5.2.3/8, je n'ai pas vu grand chose (mais je ne
| suis pas un habitué des recherches dans la norme).

Regarde l'exemple avec struct t1, struct t2 et l'appel à f() dans g().


Et ?
Il dit que l'accès au premier membre (m) n'est pas garantit car
f ne sait pas que les membres auquel elle accède sont dans une
union.

Dans le cas qui me motive (remplacer un .first par un .key,
si tu vois ce que je veux dire), toutes les fonctions
qui accéderaient connaitraient l'union, mais il ne
s'agirait pas d'une structure, mais d'un type de base.

Après, j'avoue ne rien saisir au pourquoi de la restriction
de l'exemple, ce qui l'a motivé.

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangereux
que prendre un boulevard dans le sens légal. À qui la faute ?

Avatar
Jean-Marc Bourguet
(Copie et suivi sur fr.comp.lang.c)

Gabriel Dos Reis writes:

Marc Boyer writes:


[...]

| > Oui, mais c'est un peu plus compliqué que cela. Nous avions eu cette
| > discussion maintes fois sur la liste GCC.
|
| La suite logique serait de te demander un critère de recherche dans
| les arcgives de la liste gcc, mais je ne suis pas sur d'avoir
| le courage de tout lire.

:-)

| > Regarde aussi les exemples de la norme C.
|
| A part 6.5.2.3/8, je n'ai pas vu grand chose (mais je ne
| suis pas un habitué des recherches dans la norme).

Regarde l'exemple avec struct t1, struct t2 et l'appel à f() dans
g().


Tu me rappelles que je voulais commenter la-dessus. Il dit que ceci
n'est pas valide parce que le type union n'est pas visible dans f.

struct t1 { int m; };
struct t2 { int m; };
int f(struct t1 * p1, struct t2 * p2) {
if (p1->m < 0)
p2->m = -p2->m;
return p1->m;
}
int g() {
union { struct t1 s1; struct t2 s2; } u;
/* ... */
return f(&u.s1, &u.s2);
}

Mais si

struct t1 { int m; };
struct t2 { int m; };
union u1 { struct t1 s1; struct t2 s2; };
int f(struct t1 * p1, struct t2 * p2) {
if (p1->m < 0)
p2->m = -p2->m;
return p1->m;
}
int g() {
union u1 u;
/* ... */
return f(&u.s1, &u.s2);
}

est par contre valide parce que le type union est visible, la
contrainte sur l'implementation (pour les architectures ou le premier
cas peut generer un comportement bizarre) est assez forte (des qu'on
voit une union, il faut se mettre a generer du code pessimiste dans
les acces a tous les membres de ce genre). J'aurais trouve plus
normal une contrainte telle qu'il faille faire l'acces a travers
l'union pour que ce soit valable (ce qu'en fait je pensais avant de
lire le paragraphe en question en cherchant a repondre a Marc).

Note que je suppose que le dernier membre ecrit de l'union est s1,
parce que seule la lecture est garantie par 6.5.2.3/5.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Marc Boyer
Le 21-10-2005, Marc Boyer a écrit :
Gabriel Dos Reis a écrit :
Marc Boyer writes:


Après, j'avoue ne rien saisir au pourquoi de la restriction
de l'exemple, ce qui l'a motivé.


En fait si, avec l'explication d'Antoine (1), je crois que je
devine...

Marc
(1) <dj5gg0$ie9$
--
À vélo, prendre une rue à contre-sens est moins dangereux
que prendre un boulevard dans le sens légal. À qui la faute ?


1 2 3