Structure et pointeur

Je ne parviens pas à obtenir l’adresse mémoire d’entrée d’une variable membre d’une structure. J’ai essayé de deux manières, dont l’une ne fonctionnait pas correctement. Ce serait très bien si vous me donniez des conseils.

Tout d’abord , j’ai défini une structure appelée BITMAP_HEADER.

struct BITMAP_HEADER { WORD bfType ; DWORD bfSize ; WORD bfReserved1 ; WORD bfReserved2 ; DWORD bfOffBits ; } ; 

Deuxièmement , j’ai défini et initialisé certaines variables. veuillez regarder le code ci-dessous avant de lire la ligne suivante. Dans le cas où vous me demandez pourquoi j’ai un pointeur de caractère, je devais accéder à chaque octet de l’entier bfSize.

 struct BITMAP_HEADER bitmap_header ; char* pSize = (char*)&bitmap_header.bfSize; 

Troisièmement , j’ai reçu une adresse mémoire du bfSize de deux manières différentes et imprimé les valeurs .

 1. printf("%X\n", *pSize) ; 2. printf("%X\n", (unsigned char)*(((char*)&bitmap_header)+2)) ; 

(1) directement une adresse de mémoire pour le bitmap_header.bfSize.

(2) a obtenu une adresse mémoire pour la structure BITMAP_HEADER et a déplacé le pointeur vers le prochain octet.

Enfin , voici le résultat.

 2D F6 

Pour votre information, voici les données hexadécimales de la structure BITMAP_HEADER.

 42 4D / F6 C6 2D 00 / 00 00 / 00 00 / 36 00 00 00 

Pourquoi la première méthode n’a-t-elle pas fonctionné? Je pensais que les deux méthodes étaient exactement les mêmes.

Vous courez dans la structure de remplissage ici. Le compilateur insère deux octets de remplissage entre les champs bfType et bfSize pour aligner bfSize sur une bfSize de 4 octets, car bfSize est un bfSize DWORD.

De manière générale, vous ne pouvez pas compter sur le fait de pouvoir calculer des décalages exacts au sein d’une structure, car le compilateur peut append un remplissage entre les membres. Vous pouvez contrôler cela dans une certaine mesure en utilisant des bits spécifiques au compilateur; par exemple, sur MSVC, le pack pragma , mais je ne le recommanderais pas. Le remplissage de structure permet de spécifier les ressortingctions d’alignement des membres, et certaines architectures font défaut sur les access non alignés. (D’autres personnes peuvent corriger l’alignement manuellement, mais le font généralement plutôt lentement .)

Voir aussi: http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

En ce qui concerne les données brutes dont la structure est connue à l’avance, il est généralement préférable de les lire dans un tableau et d’utiliser des décalages définis pour accéder aux champs obligatoires. De cette façon, vous n’aurez pas à vous soucier du comportement du compilateur (qui peut souvent ne pas correspondre à vos attentes). Votre code ressemblerait à ceci:

 #define FIELD_TYPE 0 #define FIELD_SIZE 2 #define FIELD_RES1 6 #define FIELD_RES2 8 #define FIELD_OFF 10 #define SIZE_HEADER 14 static uint8_t header[SIZE_HEADER]; <...> uint8_t * pheader = header; DWORD offset_bits = (DWORD)*(pheader + FIELD_OFF); 

PS pour rendre ce code portable, la taille de Word et endianness doivent être pris en compte, peu #ifdef .. #else .. #endif devrait aider avec ça.

PPS, il serait même préférable d’utiliser des opérations logiques manuelles et des opérateurs de décalage au lieu de lancer, mais cela a été décidé par souci de brièveté.