1

構造体のメンバー変数へのエントリ メモリ アドレスの取得に問題があります。2 つの方法で試しましたが、そのうちの 1 つは正しく機能しませんでした。アドバイスをいただければとても助かります。

まず、BITMAP_HEADER という名前の構造体を定義しました。

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

次に、いくつかの変数を定義して初期化しました。次の行を読む前に、以下のコードを見てください。なぜ文字ポインタを取得したのかと聞かれると、整数 bfSize の各バイトにアクセスする必要がありました。

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

3 番目に、2 つの異なる方法で bfSize のメモリ アドレスを取得し、値を出力しました。

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

(1) bitmap_header.bfSize にメモリアドレスを直接取得する。

(2) 構造体 BITMAP_HEADER へのメモリアドレスを取得し、ポインタを次へ 2 バイトシフトします。

最後に、これが結果です。

2D
F6

参考までに、構造体 BITMAP_HEADER の 16 進データを次に示します。

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

最初の方法が機能しなかったのはなぜですか? 2つの方法はまったく同じだと思いました。

4

2 に答える 2

2

ここで構造体のパディングが発生しています。コンパイラは、bfTypebfSizeフィールドの間に2バイト相当のパディングを挿入bfSizeして、4バイトのサイズに揃えます。これbfSizeはDWORDであるためです。

一般的に、コンパイラーがメンバー間にパディングを追加する可能性があるため、構造内の正確なオフセットを計算できることに依存することはできません。これは、コンパイラ固有のビットを使用してある程度制御できます。たとえば、MSVCでは、パックプラグマですが、これはお勧めしません。構造体のパディングは、メンバーの位置合わせの制限を指定するためにあり、一部のアーキテクチャーは、位置合わせされていないアクセスで障害が発生します。(他の人は手動で位置合わせを修正するかもしれませんが、通常これはかなりゆっくりと行います。)

参照: http: //en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

于 2013-01-31T10:28:29.293 に答える
0

事前に構造がわかっている生データについては、通常、それを配列に読み込み、定義されたオフセットを使用して必要なフィールドにアクセスすることをお勧めします。これにより、コンパイラの動作について心配する必要がなくなります (期待どおりにならないことがよくあります)。コードは次のようになります。

#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 このコードを移植可能にするために、WORDのサイズとエンディアンを考慮する必要があります

PPSキャストの代わりに手動の論理演算とシフト演算子を使用する方が良いでしょうが、簡潔にするためにそのままにしておきました。

于 2013-01-31T11:09:55.503 に答える