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

Portabilités des unions

27 réponses
Avatar
Nicolas Maupu
Bonjour!

Une petite question me tarraude!
Est-ce que l'union est portable d'une architecture à une autre?
Typiquement, est-ce que le programme tournera sur un sparc comme sur un ix86
(sous le même OS)?

En effet, est-ce que sur certaines machines les poids forts/faibles ne
sont-ils pas inversés?

ex:
typedef union _u_int
{
int int_val;
char char_val[4];
}u_int;

Accède-t-on au premier octet de int_val par char_val[0], char_val[3]
ou ça dépend?

Merci.

--
Nico

10 réponses

1 2 3
Avatar
Jean-Marc Bourguet
"Antoine Leca" writes:

Pierre Maurette wrote:
- A part le gain en mémoire (pas néglgeable), j'ai un peu l'impression
que les utilisations les plus intéressantes de l'union sont non
portables ;-).


L'utilisation portable de l'union, c'est... le pendant des
enregistrement variants du Pascal (et de plusieurs autres langages):
une première partie commune à tous les sous-types, qui contient les
discriminants; puis des sous-parties (se recouvrant) pour chacun des
différents sous-types.

Le truc sympa, c'est qu'avec un pointeur vers l'union, disons passé
en argument, on peut (légalement, enfin portablement) examiner les


Ta restriction m'etonne. J'avais le souvenir d'avoir verifie la
conformite de la chose; je doute que ce soit pour du C++. J'ai pas le
temps d'aller revoir ca maintenant.

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
Pierre Maurette
Pierre Maurette wrote:
- A part le gain en mémoire (pas néglgeable), j'ai un peu l'impression
que les utilisations les plus intéressantes de l'union sont non
portables ;-).


L'utilisation portable de l'union, c'est... le pendant des enregistrement
variants du Pascal (et de plusieurs autres langages): une première partie
commune à tous les sous-types, qui contient les discriminants; puis des
sous-parties (se recouvrant) pour chacun des différents sous-types.

Le truc sympa, c'est qu'avec un pointeur vers l'union, disons passé en
argument, on peut (légalement, enfin portablement) examiner les
discriminants, puis transtyper correctement et accéder aux éléments de la
sous-partie qui correspond à ce qui a été rangé réellement dans l'union
passée comme paramètre. Le degré de base du polymorphisme, mais c'est
amplement suffisant pour plein plein de choses.
Oui, j'ai effectivement vu que la norme prévoit, dans le cas d'une

union de structures, la persistence des données initiales de même type
ou de type équivalent. Tu éclaires ma lanterne sur le "sous-jacent" de
la chose. Je m'en doutais un peu.


- Je suis à peu près convaincu que, si vous vous limitez à un nombre
fini de plateformes (x86, x86-64, Sparc par exemple), l'union comme
vous voulez l'utiliser ne vous emmerdera pas,


ÀMHA, là tu t'avances... Le Sparc est gros-boutien, je crois...
Oui.


D'ailleurs, tu écris ensuite...

- Dans tous les cas, l'endianité devra être prise en compte.


... et cela suffit en général à faire que les utilisations un peu trop
tangentes des unions deviennent caduques.
En fait, sachant que x86 et Sparc étaient d'endianités différentes, le

code proposé (ou l'utilisation abusive de l'union) était d'abord un
code de diagnostic de l'endianité. Il aurait d'ailleurs peut-être fallu
affiner, il n'y a pas que 2 façons d'écrire des 32 bits dans une
mémoire dont "l'atome" est de 8 bits.



Une question, souhaitez-vous accèder à votre int par char ou par
octet ?


Taquin, va...
Nunca jamas ....


--
Pierre

--
Ceci est une signature automatique de MesNews.
Site : http://www.mesnews.net


Avatar
Antoine Leca
Jean-Marc Bourguet wrote:
"Antoine Leca" writes:
Le truc sympa, c'est qu'avec un pointeur vers l'union, disons passé
en argument, on peut (légalement, enfin portablement) examiner les


Ta restriction m'etonne.


Tu as raison d'être étonné!

J'ai écrit légalement parce que c'est le cas, puis, dans un effort pour
éviter de rendre ce fil inaccessible aux nouveaux venus et d'éviter de
circonscrire le débat à des querelles d'experts sur le sexe de la norme (cf.
des discussions récentes), j'avais ajouté le mot portable pour essayer de me
rendre plus abordable ou plus intéressant.
En d'aures termes, le « enfin » ci-dessus n'est pas exclusif, c'est une
simple conjonction. Cette utilisation est portable (ce qui importe), et elle
est « légale » (quelque soit le sens que l'on donne à ce mot).


Rassuré ? ;-)


Antoine


Avatar
Antoine Leca
Pierre Maurette wrote:
Il aurait d'ailleurs peut-être fallu affiner, il n'y a pas que
2 façons d'écrire des 32 bits dans une mémoire dont "l'atome"
est de 8 bits.


Certes, mais les autres manières sont ou des dinosaures, ou des mirages.

Tout le monde (ou presque ;-)) se rappelle du cas du PDP-11 (machine
purement 16 bits, petit-boutienne), version Unix, où les entiers de 32 bits
sont généralement rangés dans l'ordre naturel (pour des humains), c'est à
dire mot de poids fort avant mot de poids faible. Au résultat, 0x01020304
est rangé en mémoire
(adr.basse) 0x0102
(adr.haute) 0x0304
d'où en octets "2143". Ce qui n'est ni le petit boutien "4321"
(x86), ni le gros boutien "1234" (Sparc). Mais cela reste l'exception
qui confirme la règle; et ici elle aurait été mise de côté par l'implicite
règle que le type int est sur 32 bits!

Bien sûr il y a aussi le cas des machines gros boutiennes où les entiers de
32 bits sont rangés sur 64 bits, seule unité connue par la bécane. On aura
alors "1234". Etc.


Antoine

Avatar
Emmanuel Delahaye
Pierre Maurette wrote on 13/04/05 :
- A part le gain en mémoire (pas néglgeable), j'ai un peu l'impression que
les utilisations les plus intéressantes de l'union sont non portables ;-).


Je m'en sert pour faire du paramètrage souple mais déterministe :

struct
{
selector a, b, c
union
{
struct a
{
...
}
struct b
{
...
}
struct c
{
...
}
c
}
}

--
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
Antoine Leca wrote on 13/04/05 :
L'utilisation portable de l'union, c'est... le pendant des enregistrement
variants du Pascal (et de plusieurs autres langages): une première partie
commune à tous les sous-types, qui contient les discriminants; puis des
sous-parties (se recouvrant) pour chacun des différents sous-types.


Exactement.

--
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
"Antoine Leca" writes:

Cette utilisation est portable (ce qui importe),


Nous sommes d'accord.

et elle est « légale » (quelque soit le sens que l'on
donne à ce mot).

Rassuré ? ;-)


Ce n'est pas quelque chose qui m'inquiétait outre mesure:
toutes les plateformes qui m'intéressent ont Xlib :-)

--
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
JeanPascal
Les unions / structures qui sont portées vers d'autres architectures et/ou
OS peuvent présenter quelques soucis du type :

- Pour les architectures little-big endian (quelque soit l'OS) : Probleme de
relecture des donnees enregistrees sur une autre architecture. Pour cela et
en ce qui me concerne j'ai resolu le probleme en utilisant une fonction qui
permute les octets des variables de type binaire (int et autre short ..)
dans l'ordre voulu (peut etre perte de perf, mais pas sensible du tout !).
Attention aux problemes plus important avec les champs de bits !!
En tout cas ca marche depuis ... de nombreuses annees (6)

- Pour d'autres OS mais surtout a mon avis en fonction des compilos :
Probleme d'alignement pour les unions de structures. Developpant des codes
devant tourner sur des machines HP (en PA-RISC avec un compilo HP) et
Windows (Intel ou AMD avec un compilo krosoft), j'evite les problemes en
"paddant" moi meme les strcutures sur la taille du int (4 octets pour les
compilos recents)

Jean-Pascal


"Patrick 'Zener' Brunet" a écrit dans
le message de news: 425beb54$1$29261$
Bonjour.

"Nicolas Maupu" a écrit dans le message de
news: d3govc$h3l$
Bonjour!

Une petite question me tarraude!
Est-ce que l'union est portable d'une architecture à une autre?
Typiquement, est-ce que le programme tournera sur un sparc comme sur un
ix86

(sous le même OS)?

En effet, est-ce que sur certaines machines les poids forts/faibles ne
sont-ils pas inversés?

ex:
typedef union _u_int
{
int int_val;
char char_val[4];
}u_int;

Accède-t-on au premier octet de int_val par char_val[0], char_val[3]
ou ça dépend?



L'union est portable, c'est ce que l'on peut en faire, ça en l'occurence,
qui ne l'est pas.

Vous ne pouvez pas faire tourner un code ainsi conçu pour un mapping "big
endian" sur une machine "little endian" et inversement : c'est la
portabilité conceptuelle qui entre en jeu.

Par contre vous pouvez imaginer de remplacer les indices 0 à 3 par des
constantes (macros) définies de manière adéquate par rapport à
"l'endianicité" de la plate-forme.

Au-delà (si le compilo le permet) vous pouvez même envisager (mais là plus
au niveau du préprocesseur) de déterminer cette caractéristique
automatiquement en utilisant une construction du même genre : mappez une
telle structure sur une constante de taille int et de valeur 1, et
considérez la valeur booléenne de char_val[0].
Mais en général cette information figure dans les headers standards, donc
une telle manoeuvre est inutile.

Il faut également se demander si un int est toujours de taille 32 bits. Là
aussi, en général il vaut mieux que le code se calibre sur les headers
standards dûment documentés par le fabricant du compilo.

Dans ces conditions, ça peut devenir 100% portable.

Cordialement,

--

/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/





Avatar
Patrick 'Zener' Brunet
Bonsoir.

"JeanPascal" a écrit dans le message de
news: 425d7b79$0$19355$
Les unions / structures qui sont portées vers d'autres architectures et/ou
OS peuvent présenter quelques soucis du type :

- Pour les architectures little-big endian (quelque soit l'OS) : Probleme
de

relecture des donnees enregistrees sur une autre architecture. Pour cela
et

en ce qui me concerne j'ai resolu le probleme en utilisant une fonction
qui

permute les octets des variables de type binaire (int et autre short ..)
dans l'ordre voulu (peut etre perte de perf, mais pas sensible du tout !).


Oui, c'est ce que je proposais de faire avec une macro. Par rapport à ce que
vous dites plus bas sur l'alignement, normalement la règle d'alignement est
bien définie : en se limitant aux deux types envisagés (éventuellement
synchronisés au moyen d'une structure anonyme), s'il n'y a pas de faute
d'alignement pour le int, le char[0] ne peut que tomber au même endroit...
Par ailleurs je ne crois pas qu'il puisse y avoir du padding dans un tableau
de char... Là évidemment ça serait moche.

Attention aux problemes plus important avec les champs de bits !!


Ca franchement je ne crois pas qu'il soit raisonnable de les utiliser pour
autre chose que de l'accès direct à du hardware. J'ai toujours utilisé les
masques binaires pour mes flags 100% code.

En tout cas ca marche depuis ... de nombreuses annees (6)



Ben oui, chez moi aussi ! C'était le sens de mon intervention. Si c'est
conceptuellement correct par rapport à la plate-forme, le compilo ne va pas
f... le b... pour le principe.

- Pour d'autres OS mais surtout a mon avis en fonction des compilos :
Probleme d'alignement pour les unions de structures. Developpant des codes
devant tourner sur des machines HP (en PA-RISC avec un compilo HP) et
Windows (Intel ou AMD avec un compilo krosoft), j'evite les problemes en
"paddant" moi meme les strcutures sur la taille du int (4 octets pour les
compilos recents)



Il y a des contraintes souvent liées aux librairies pré-compilées, et
utilisant des options d'alignement part le biais de pragmas (zéro-padding
pour Windows par exemple). Il suffit de faire une compilation conditionnelle
alignée sur les mêmes options.
4 octets je ne suis pas sûr. S'il y a des types double ou long double dans
la structure, ça peut poser problème.
A l'heure actuelle, je crois que même les librairies NT arrivent à s'aligner
sur du 16 octets pour certaines plates-formes.

Mais de toute manière ça sort du cadre initial de ce thread : extraire les
octets d'un int.

Quand j'utilise des unions plus importantes, c'est souvent pour gagner de la
place dans des structures de données comportant des alternatives partielles
(le choix étant contextuel). C'est très fréquent dans les paramètres-blocs
de requêtes, ou les structures dynamiques en Intelligence Artificielle...
Mais donc là on est parfaitement maître de ce qu'on fait : il n'y a plus
aucun lien entre les membres de l'union.

Cordialement,

--

/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/

Avatar
Jean-Louis Liagre
- Je suis à peu près convaincu que, si vous vous limitez à un nombre
fini de plateformes (x86, x86-64, Sparc par exemple), l'union comme
vous voulez l'utiliser ne vous emmerdera pas,



ÀMHA, là tu t'avances... Le Sparc est gros-boutien, je crois...


Oui.



Pas tout à fait, depuis une dizaine d'années, l'architecture SPARC v9
(ultraSPARC, 64 bits) permet de basculer d'un mode à l'autre "à chaud",
et meme d'avoir un mode mixte ou l'O/S (supervisor) est big endian mais
une application (user mode) est little endian ...
Je ne l'ai jamais vu mis en oeuvre et c'est toujours le big-endian qui
est utilisé, mais un jour quelqu'un se lancera peut-etre ...



1 2 3