次のようなC構造体があるとします。
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData; } tempStruct;
構造体のこれら3つのメンバーすべてを単一の32ビットワードに入れながら、それらに個別にアクセスできるようにする方法はありますか?
の助けを借りて何かunion
?
typedef struct {
UINT8 nRow;
UINT8 nCol;
UINT16 nData;
}
tempStruct;
typedef union {
tempStruct myStruct;
UINT32 myWord;
} stuff;
またはさらに良い(「中間」構造体なし):
#include <stdlib.h>
#include <stdio.h>
typedef union {
struct {
int nRow:8;
int nCol:8;
int nData:16;
};
int myWord;
} stuff;
int main(int args, char** argv){
stuff a;
a.myWord=0;
a.nCol=2;
printf("%d\n", a.myWord);
return 0;
}
それをUINT32と呼ぶのはどうですか?Cがタイプセーフであるとは限りません。
tempStruct t;
t.nRow = 0x01;
t.nCol = 0x02;
t.nData = 0x04;
//put a reference to the struct as a pointer to a UINT32
UINT32* word = (UINT32 *) &t;
printf("%x", *word);
次に、ポインタを逆参照することにより、構造体の値を32ビットワードとして取得できます。ただし、システムの詳細が重要になる場合があります...これを自分のマシンで実行すると、の値word
は0x00040201---つまり、フィールドの順序が逆になります。これを別のシステムにシリアル化しようとしている場合、必ずしもそうなるとは思わないので、移植性はありません。
実際に32ビット整数として格納してから、フィールドを個別に参照したい場合は、どうでしょうか。
UINT32 word = 0x01020004;
そしてどこか他の場所...
UINT8* row(UINT32 word) {
return (UINT8 *) &word + 3;
}
UINT8* col(UINT32 word) {
return ((UINT8 *) &word) + 2;
}
UINT16* data(UINT32 word) {
return ((UINT16 *) &word);
}
マクロは、ポータブルエンディアンを促進します。
はい、Cのビットフィールドを使用してそれを行うことができます。何かのようなもの:
typedef struct {
unsigned nRow : 8;
unsigned nCol : 8;
unsigned nData : 16;
} tempStruct;
メモリレイアウトも制御したい場合は、を確認することをお勧めします#pragma pack
。このために一部のコンパイラで使用できる移植性のないオプション。
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
nRowは8ビットのみを使用し、nColは8ビットを使用し、nDateは16ビットを使用します。
これはあなたのために働くでしょう。
サイズを確認するためにサンプルプログラムを作成しました
#include<stdio.h>
typedef struct {
int nRow:8;
int nCol:8;
int nData:16; } tempStruct;
typedef struct {
int nRow;
int nCol;
int nData; } tempStructZ;
int main(void) {
printf("%d\n", sizeof(tempStruct));
printf("%d\n", sizeof(tempStructZ));
return 0;
}
出力:4 16