Selon la norme, comportement indéfini. En practice, si les deux accès ont lieu dans des unités de compilation (ou qu'on compile sans optimisation), il y a de fortes chances que ça marche.
-- James Kanze
Fabien LE LEZ wrote:
On Wed, 05 Apr 2006 14:35:03 +0200, Aurelien Regat-Barrel
<nospam.aregatba@yahoo.fr>:
void Test( long Value )
{
Example( reinterpret_cast<union_t*>( &Value ) );
}
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est
aléatoire.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)"
{
union_t mon_t;
mon_t.l= Value;
Example (&mon_t);
}
Par ailleurs, il me semble que le comportement de ce code est
indéfini :
Selon la norme, comportement indéfini. En practice, si les deux
accès ont lieu dans des unités de compilation (ou qu'on compile
sans optimisation), il y a de fortes chances que ça marche.
Selon la norme, comportement indéfini. En practice, si les deux accès ont lieu dans des unités de compilation (ou qu'on compile sans optimisation), il y a de fortes chances que ça marche.
-- James Kanze
Aurelien Regat-Barrel
void Test( long Value ) { Example( reinterpret_cast<union_t*>( &Value ) ); }
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est aléatoire.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)" { union_t mon_t; mon_t.l= Value; Example (&mon_t); }
Ok. C'était pour économiser 2 lignes :-) Cela dit, je ne comprends pas trop pourquoi c'est un problème. Pour moi l'union c'est (entre autre) un autre moyen de faire du cast.
Par ailleurs, il me semble que le comportement de ce code est indéfini :
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque. Ca voudrait dire que c'est spécifique à chaque compilo ?
-- Aurélien Regat-Barrel
void Test( long Value )
{
Example( reinterpret_cast<union_t*>( &Value ) );
}
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est aléatoire.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)"
{
union_t mon_t;
mon_t.l= Value;
Example (&mon_t);
}
Ok. C'était pour économiser 2 lignes :-)
Cela dit, je ne comprends pas trop pourquoi c'est un problème. Pour moi
l'union c'est (entre autre) un autre moyen de faire du cast.
Par ailleurs, il me semble que le comportement de ce code est
indéfini :
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type
d'union est pas mal utilisé pour faciliter la manipulation des octets
d'une donnée quelconque. Ca voudrait dire que c'est spécifique à chaque
compilo ?
void Test( long Value ) { Example( reinterpret_cast<union_t*>( &Value ) ); }
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est aléatoire.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)" { union_t mon_t; mon_t.l= Value; Example (&mon_t); }
Ok. C'était pour économiser 2 lignes :-) Cela dit, je ne comprends pas trop pourquoi c'est un problème. Pour moi l'union c'est (entre autre) un autre moyen de faire du cast.
Par ailleurs, il me semble que le comportement de ce code est indéfini :
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque. Ca voudrait dire que c'est spécifique à chaque compilo ?
-- Aurélien Regat-Barrel
James Kanze
Aurelien Regat-Barrel wrote:
void Test( long Value ) { Example( reinterpret_cast<union_t*>( &Value ) ); }
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est aléatoir e.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)" { union_t mon_t; mon_t.l= Value; Example (&mon_t); }
Ok. C'était pour économiser 2 lignes :-)
Cela dit, je ne comprends pas trop pourquoi c'est un problème. Pour moi l'union c'est (entre autre) un autre moyen de faire du cast.
Par ailleurs, il me semble que le comportement de ce code est indéfini :
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été, et en général, ça ne marche pas avec beaucoup de compilateurs ; par exemple, le compilateur voit que la valeur écrite dan mon_t.l n'est jamais utilisée, et supprime l'écriture.
Ca voudrait dire que c'est spécifique à chaque compilo ?
Ça veut dire que ça pourrait bien marcher dans les build de développement, mais non dans les builds de production.
-- James Kanze
Aurelien Regat-Barrel wrote:
void Test( long Value )
{
Example( reinterpret_cast<union_t*>( &Value ) );
}
Cet utilisation de reinterpret_cast est-elle problématique ?
Oui. C'est sérieusement casse-gueule, et le résultat est aléatoir e.
Il y a bien plus élégant, fiable et prévisible :
void Test (long Value)// ou "(long const& Value)"
{
union_t mon_t;
mon_t.l= Value;
Example (&mon_t);
}
Ok. C'était pour économiser 2 lignes :-)
Cela dit, je ne comprends pas trop pourquoi c'est un problème.
Pour moi l'union c'est (entre autre) un autre moyen de faire
du cast.
Par ailleurs, il me semble que le comportement de ce code est
indéfini :
Si ton sentiment est confirmé, ça remet en cause le miens. Ce
type d'union est pas mal utilisé pour faciliter la
manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de
l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
et en général, ça ne marche pas avec beaucoup de compilateurs ;
par exemple, le compilateur voit que la valeur écrite dan
mon_t.l n'est jamais utilisée, et supprime l'écriture.
Ca voudrait dire que c'est spécifique à chaque compilo ?
Ça veut dire que ça pourrait bien marcher dans les build de
développement, mais non dans les builds de production.
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été, et en général, ça ne marche pas avec beaucoup de compilateurs ; par exemple, le compilateur voit que la valeur écrite dan mon_t.l n'est jamais utilisée, et supprime l'écriture.
Ca voudrait dire que c'est spécifique à chaque compilo ?
Ça veut dire que ça pourrait bien marcher dans les build de développement, mais non dans les builds de production.
-- James Kanze
Bruno CAUSSE
dans l'article , James Kanze à a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
dans l'article 1144407852.748517.197140@v46g2000cwv.googlegroups.com, James
Kanze à kanze.james@neuf.fr a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément de
l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
dans l'article , James Kanze à a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Aurelien Regat-Barrel
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été, et en général, ça ne marche pas avec beaucoup de compilateurs ; par exemple, le compilateur voit que la valeur écrite dan mon_t.l n'est jamais utilisée, et supprime l'écriture.
J'ai deux exemples en tête. Un ancien, du temps de DOS, pour la représentation des registres du CPU:
Utilisé par SetFilePointerEx par exemple (equivalent de seek): http://msdn.microsoft.com/library/en-us/fileio/fs/setfilepointer.asp
Le type LARGE_INTEGER est utilisé par de nombreux compilos C/C++ sous Windows, et je pense que ça marche à chaque fois.
-- Aurélien Regat-Barrel
Si ton sentiment est confirmé, ça remet en cause le miens. Ce
type d'union est pas mal utilisé pour faciliter la
manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de
l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
et en général, ça ne marche pas avec beaucoup de compilateurs ;
par exemple, le compilateur voit que la valeur écrite dan
mon_t.l n'est jamais utilisée, et supprime l'écriture.
J'ai deux exemples en tête. Un ancien, du temps de DOS, pour la
représentation des registres du CPU:
Si ton sentiment est confirmé, ça remet en cause le miens. Ce type d'union est pas mal utilisé pour faciliter la manipulation des octets d'une donnée quelconque.
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été, et en général, ça ne marche pas avec beaucoup de compilateurs ; par exemple, le compilateur voit que la valeur écrite dan mon_t.l n'est jamais utilisée, et supprime l'écriture.
J'ai deux exemples en tête. Un ancien, du temps de DOS, pour la représentation des registres du CPU:
Utilisé par SetFilePointerEx par exemple (equivalent de seek): http://msdn.microsoft.com/library/en-us/fileio/fs/setfilepointer.asp
Le type LARGE_INTEGER est utilisé par de nombreux compilos C/C++ sous Windows, et je pense que ça marche à chaque fois.
-- Aurélien Regat-Barrel
Fabien LE LEZ
On Fri, 07 Apr 2006 10:44:22 +0200, Aurelien Regat-Barrel :
Pour moi l'union c'est (entre autre) un autre moyen de faire du cast.
Ben non. Un union est juste un moyen d'économiser de la place, quand on sait qu'à un moment donné d'un programme, on n'utilisera qu'une partie des membres. En fait, "union" n'est rien d'autre qu'une optimisation. Si, en remplaçant "union" par "struct" partout dans ton code, le sens du programme change, il y a des chances pour que ton code de départ ait un comportement indéfini.
Par ailleurs, quand tu écris :
union union_t { struct s { short low; short high; } u; long l; };
tu as l'air de penser que sizeof(union_t::s)==sizeof(long). Y a-t-il un argument qui justifierait cela ?
On Fri, 07 Apr 2006 10:44:22 +0200, Aurelien Regat-Barrel
<nospam.aregatba@yahoo.fr>:
Pour moi
l'union c'est (entre autre) un autre moyen de faire du cast.
Ben non. Un union est juste un moyen d'économiser de la place, quand
on sait qu'à un moment donné d'un programme, on n'utilisera qu'une
partie des membres.
En fait, "union" n'est rien d'autre qu'une optimisation. Si, en
remplaçant "union" par "struct" partout dans ton code, le sens du
programme change, il y a des chances pour que ton code de départ ait
un comportement indéfini.
Par ailleurs, quand tu écris :
union union_t {
struct s {
short low;
short high;
} u;
long l;
};
tu as l'air de penser que sizeof(union_t::s)==sizeof(long).
Y a-t-il un argument qui justifierait cela ?
On Fri, 07 Apr 2006 10:44:22 +0200, Aurelien Regat-Barrel :
Pour moi l'union c'est (entre autre) un autre moyen de faire du cast.
Ben non. Un union est juste un moyen d'économiser de la place, quand on sait qu'à un moment donné d'un programme, on n'utilisera qu'une partie des membres. En fait, "union" n'est rien d'autre qu'une optimisation. Si, en remplaçant "union" par "struct" partout dans ton code, le sens du programme change, il y a des chances pour que ton code de départ ait un comportement indéfini.
Par ailleurs, quand tu écris :
union union_t { struct s { short low; short high; } u; long l; };
tu as l'air de penser que sizeof(union_t::s)==sizeof(long). Y a-t-il un argument qui justifierait cela ?
Fabien LE LEZ
On Fri, 07 Apr 2006 14:32:31 +0200, Bruno CAUSSE :
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Les "union", comme toute optimisation, sont utilisés quand on s'aperçoit que le programme doit être optimisé.
On Fri, 07 Apr 2006 14:32:31 +0200, Bruno CAUSSE <envoi@lesSpam.fr>:
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Les "union", comme toute optimisation, sont utilisés quand on
s'aperçoit que le programme doit être optimisé.
On Fri, 07 Apr 2006 14:32:31 +0200, Bruno CAUSSE :
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Les "union", comme toute optimisation, sont utilisés quand on s'aperçoit que le programme doit être optimisé.
Fabien LE LEZ
On Fri, 07 Apr 2006 15:46:14 +0200, Aurelien Regat-Barrel :
Le type LARGE_INTEGER est utilisé par de nombreux compilos C/C++ sous Windows, et je pense que ça marche à chaque fois.
Note que windows.h est un header généralement fourni avec le compilo (ou, au moins, testé par les développeurs de ce compilo). Par conséquent, l'éditeur de chaque compilo s'est assuré que le cas "LARGE_INTEGER" fonctionne.
Mais il s'agit bien sûr d'un cas où la portabilité est totalement abandonnée.
On Fri, 07 Apr 2006 15:46:14 +0200, Aurelien Regat-Barrel
<nospam.aregatba@yahoo.fr>:
Le type LARGE_INTEGER est utilisé par de nombreux compilos C/C++ sous
Windows, et je pense que ça marche à chaque fois.
Note que windows.h est un header généralement fourni avec le compilo
(ou, au moins, testé par les développeurs de ce compilo). Par
conséquent, l'éditeur de chaque compilo s'est assuré que le cas
"LARGE_INTEGER" fonctionne.
Mais il s'agit bien sûr d'un cas où la portabilité est totalement
abandonnée.
On Fri, 07 Apr 2006 15:46:14 +0200, Aurelien Regat-Barrel :
Le type LARGE_INTEGER est utilisé par de nombreux compilos C/C++ sous Windows, et je pense que ça marche à chaque fois.
Note que windows.h est un header généralement fourni avec le compilo (ou, au moins, testé par les développeurs de ce compilo). Par conséquent, l'éditeur de chaque compilo s'est assuré que le cas "LARGE_INTEGER" fonctionne.
Mais il s'agit bien sûr d'un cas où la portabilité est totalement abandonnée.
James Kanze
Bruno CAUSSE wrote:
dans l'article , James Kanze à a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Bonne question:-).
Je m'en sers actuellement surtout pour assurer l'alignement :
union { unsigned char rawMemory[ sizeof( T ) ] ; double dummyForAlignment ; } ;
Sinon, c'est utile (mais plutôt pour des raisons historiques) pour les valeurs sémantiques dans yacc ou bison.
Et évidemment, il y a bien des programmes qui traitent des ensembles de données de plusieurs milliards d'éléments. Parfois en flottant, parfois en fixe. Alors, en attendant avoir la mémoire qui correspond à l'adressage 64 bits... (Note bien que quand tu traites de très grands tableaux comme ça, plus tu tiens en mémoire réele, moins ton programme swappe. Ce qui peut être important aussi.)
-- James Kanze 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
Bruno CAUSSE wrote:
dans l'article
1144407852.748517.197140@v46g2000cwv.googlegroups.com, James
Kanze à kanze.james@neuf.fr a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément
de l'union autre que le dernier qu'on a écrit. Ça l'a
toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent
les unions?
Bonne question:-).
Je m'en sers actuellement surtout pour assurer l'alignement :
union
{
unsigned char rawMemory[ sizeof( T ) ] ;
double dummyForAlignment ;
} ;
Sinon, c'est utile (mais plutôt pour des raisons historiques)
pour les valeurs sémantiques dans yacc ou bison.
Et évidemment, il y a bien des programmes qui traitent des
ensembles de données de plusieurs milliards d'éléments. Parfois
en flottant, parfois en fixe. Alors, en attendant avoir la
mémoire qui correspond à l'adressage 64 bits... (Note bien que
quand tu traites de très grands tableaux comme ça, plus tu tiens
en mémoire réele, moins ton programme swappe. Ce qui peut être
important aussi.)
--
James Kanze kanze.james@neuf.fr
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
dans l'article , James Kanze à a écrit le 7/04/06 13:04 :
Par qui ? C'est un comportement indéfini de lire un élément de l'union autre que le dernier qu'on a écrit. Ça l'a toujours été,
Ok.
Maintemenant avec nos machines a plusieurs Go a quoi servent les unions?
Bonne question:-).
Je m'en sers actuellement surtout pour assurer l'alignement :
union { unsigned char rawMemory[ sizeof( T ) ] ; double dummyForAlignment ; } ;
Sinon, c'est utile (mais plutôt pour des raisons historiques) pour les valeurs sémantiques dans yacc ou bison.
Et évidemment, il y a bien des programmes qui traitent des ensembles de données de plusieurs milliards d'éléments. Parfois en flottant, parfois en fixe. Alors, en attendant avoir la mémoire qui correspond à l'adressage 64 bits... (Note bien que quand tu traites de très grands tableaux comme ça, plus tu tiens en mémoire réele, moins ton programme swappe. Ce qui peut être important aussi.)
-- James Kanze 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