Et si tu es en big-endian, tu te retrouves avec bar[0] == 0x64 etc.
en little-endian aussi !... bar[0] == bar[3] :)
Sylvain.
Michael
// valable pour proc. big-endian union composite { DWORD int32; struct { char lo; char m1; char m2; char hi; }; };
int main(){ composite fourCC; fourCC.int32 = 0x64737664; char a = fourCC.hi; char b = fourCC.m2; char c = fourCC.m1; char d = fourCC.lo; }
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
Est-ce parce que comme la structure et le DWORD partagent le même espace en mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les même 4 octets occupés par les membres de la structure?
Et concernant l'alignement des données, je suppose qu'il peut poser problème dans le cas où le compilo déciderait que pour stocker l'union, il ne choisirait pas 4 octets contigus?
// valable pour proc. big-endian
union composite {
DWORD int32;
struct {
char lo;
char m1;
char m2;
char hi;
};
};
int main(){
composite fourCC;
fourCC.int32 = 0x64737664;
char a = fourCC.hi;
char b = fourCC.m2;
char c = fourCC.m1;
char d = fourCC.lo;
}
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
Est-ce parce que comme la structure et le DWORD partagent le même espace en
mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les
même 4 octets occupés par les membres de la structure?
Et concernant l'alignement des données, je suppose qu'il peut poser problème
dans le cas où le compilo déciderait que pour stocker l'union, il ne
choisirait pas 4 octets contigus?
// valable pour proc. big-endian union composite { DWORD int32; struct { char lo; char m1; char m2; char hi; }; };
int main(){ composite fourCC; fourCC.int32 = 0x64737664; char a = fourCC.hi; char b = fourCC.m2; char c = fourCC.m1; char d = fourCC.lo; }
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
Est-ce parce que comme la structure et le DWORD partagent le même espace en mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les même 4 octets occupés par les membres de la structure?
Et concernant l'alignement des données, je suppose qu'il peut poser problème dans le cas où le compilo déciderait que pour stocker l'union, il ne choisirait pas 4 octets contigus?
Sylvain
Michael wrote on 12/09/2006 01:34:
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
dans le cas souhaité par celui qui code (le compilo peut avoir une autre opinion) l'adresse de 'int32' est la même que celle de la struct anonyme; donc affecter int32 affecte les 4 chars, inversement affecter un des chars changerait l'octet de même adresse du long.
Est-ce parce que comme la structure et le DWORD partagent le même espace en mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les même 4 octets occupés par les membres de la structure?
oui.
Et concernant l'alignement des données, je suppose qu'il peut poser problème dans le cas où le compilo déciderait que pour stocker l'union, il ne choisirait pas 4 octets contigus?
oui, même si c'est peu probable, il alignera le champ suivant (y'en a pas ici) selon cette valeur d'alignement mais la struct de 4 x 8 peut rester comme cela ... ça dépends.
ça reste une mauvaise façon de faire pour les cas où l'on n'a pas droit aux hypothèses (ie compilo, options diverses, non toutes maîtrisées).
il vaut mieux utiliser le mode verbieux de ma première réponse, ou si vous voulez jouer avec les adresses et comme indiqué par loufoque: char* ptr = (char*) &fourCC; puis lire ptr[i] (0<=i<4).
Sylvain.
Michael wrote on 12/09/2006 01:34:
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
dans le cas souhaité par celui qui code (le compilo peut avoir une autre
opinion) l'adresse de 'int32' est la même que celle de la struct
anonyme; donc affecter int32 affecte les 4 chars, inversement affecter
un des chars changerait l'octet de même adresse du long.
Est-ce parce que comme la structure et le DWORD partagent le même espace en
mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les
même 4 octets occupés par les membres de la structure?
oui.
Et concernant l'alignement des données, je suppose qu'il peut poser problème
dans le cas où le compilo déciderait que pour stocker l'union, il ne
choisirait pas 4 octets contigus?
oui, même si c'est peu probable, il alignera le champ suivant (y'en a
pas ici) selon cette valeur d'alignement mais la struct de 4 x 8 peut
rester comme cela ... ça dépends.
ça reste une mauvaise façon de faire pour les cas où l'on n'a pas droit
aux hypothèses (ie compilo, options diverses, non toutes maîtrisées).
il vaut mieux utiliser le mode verbieux de ma première réponse, ou si
vous voulez jouer avec les adresses et comme indiqué par loufoque:
char* ptr = (char*) &fourCC; puis lire ptr[i] (0<=i<4).
Je ne comprends pas très bien comment fonctionne ce code.
Comment le compilo peut-il donner les bonnes valeurs à fourCC.hi, etc...
dans le cas souhaité par celui qui code (le compilo peut avoir une autre opinion) l'adresse de 'int32' est la même que celle de la struct anonyme; donc affecter int32 affecte les 4 chars, inversement affecter un des chars changerait l'octet de même adresse du long.
Est-ce parce que comme la structure et le DWORD partagent le même espace en mémoire, du coup les 4 octets occupés par le DWORD se retrouvent être les même 4 octets occupés par les membres de la structure?
oui.
Et concernant l'alignement des données, je suppose qu'il peut poser problème dans le cas où le compilo déciderait que pour stocker l'union, il ne choisirait pas 4 octets contigus?
oui, même si c'est peu probable, il alignera le champ suivant (y'en a pas ici) selon cette valeur d'alignement mais la struct de 4 x 8 peut rester comme cela ... ça dépends.
ça reste une mauvaise façon de faire pour les cas où l'on n'a pas droit aux hypothèses (ie compilo, options diverses, non toutes maîtrisées).
il vaut mieux utiliser le mode verbieux de ma première réponse, ou si vous voulez jouer avec les adresses et comme indiqué par loufoque: char* ptr = (char*) &fourCC; puis lire ptr[i] (0<=i<4).
Sylvain.
kanze
Michael wrote:
soit le DWORD suivant:
DWORD fourCC = 1685288548, soit 0x64737664;
DWORD est un typedef à un type entier ? (D'après le nom, d'au moins 64 bits, ou ?)
En le découpant en:
char a = 0x64; char b = 0x73; char c = 0x76; char d = 0x64;
J'ai a = 'd', b = 'v' , c = 's' , d = 'd'
Seulement, comment "couper" le dword en 4 char ?
Si j'ai bien compris, pour le caractère a, tu veux des bits 24 à 31. Donc : a = (fourCC >> 24) & 0xFF ;
Tu fais pareil pour les autres caractères : à chaque fois, tu définis grosso modo le bit de poids faible, et tu décales à droite pour mettre ce bit dans le bit 0 ; ensuite, tu masques avec le nombre de bits voulus. Donc, avec les valeurs que tu as données, tu as des décalages de 24, de 16, de 8 et de 0 bits, avec chaque fois une masque de 0x7F ou 0xFF (selon que tu souhaites de l'ASCII, ou un autre encodage, genre ISO 8859-1).
En général, en revanche, il est préférable de ne pas passer par là. S'il s'agit des caractères, on les stocke dans un std::string, ou à la rigueur dans un char[]. (Ou dans un std::wstring ou wchar_t[], pour des encodages qui l'exigent.)
-- 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
Michael wrote:
soit le DWORD suivant:
DWORD fourCC = 1685288548, soit 0x64737664;
DWORD est un typedef à un type entier ? (D'après le nom, d'au
moins 64 bits, ou ?)
En le découpant en:
char a = 0x64;
char b = 0x73;
char c = 0x76;
char d = 0x64;
J'ai a = 'd', b = 'v' , c = 's' , d = 'd'
Seulement, comment "couper" le dword en 4 char ?
Si j'ai bien compris, pour le caractère a, tu veux des bits 24 à
31. Donc :
a = (fourCC >> 24) & 0xFF ;
Tu fais pareil pour les autres caractères : à chaque fois, tu
définis grosso modo le bit de poids faible, et tu décales à
droite pour mettre ce bit dans le bit 0 ; ensuite, tu masques
avec le nombre de bits voulus. Donc, avec les valeurs que tu as
données, tu as des décalages de 24, de 16, de 8 et de 0 bits,
avec chaque fois une masque de 0x7F ou 0xFF (selon que tu
souhaites de l'ASCII, ou un autre encodage, genre ISO 8859-1).
En général, en revanche, il est préférable de ne pas passer par
là. S'il s'agit des caractères, on les stocke dans un
std::string, ou à la rigueur dans un char[]. (Ou dans un
std::wstring ou wchar_t[], pour des encodages qui l'exigent.)
--
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
DWORD est un typedef à un type entier ? (D'après le nom, d'au moins 64 bits, ou ?)
En le découpant en:
char a = 0x64; char b = 0x73; char c = 0x76; char d = 0x64;
J'ai a = 'd', b = 'v' , c = 's' , d = 'd'
Seulement, comment "couper" le dword en 4 char ?
Si j'ai bien compris, pour le caractère a, tu veux des bits 24 à 31. Donc : a = (fourCC >> 24) & 0xFF ;
Tu fais pareil pour les autres caractères : à chaque fois, tu définis grosso modo le bit de poids faible, et tu décales à droite pour mettre ce bit dans le bit 0 ; ensuite, tu masques avec le nombre de bits voulus. Donc, avec les valeurs que tu as données, tu as des décalages de 24, de 16, de 8 et de 0 bits, avec chaque fois une masque de 0x7F ou 0xFF (selon que tu souhaites de l'ASCII, ou un autre encodage, genre ISO 8859-1).
En général, en revanche, il est préférable de ne pas passer par là. S'il s'agit des caractères, on les stocke dans un std::string, ou à la rigueur dans un char[]. (Ou dans un std::wstring ou wchar_t[], pour des encodages qui l'exigent.)
-- 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