ホーム » スタッフ » 斉藤徹 » 構造体のワード境界

2015年10月
« 9月   11月 »
 123
45678910
11121314151617
18192021222324
25262728293031

最近の投稿(電子情報)

アーカイブ

カテゴリー

構造体のワード境界

今日は、構造体を使ったプログラミングの演習。 単純な演習だけでは、来週に研修旅行を予定している3年は授業の遅れも心配なので、 前半にワード境界の話をする。

ワード境界

struct Data {
   char name[3] ;
   int  point ;
} ;
struct Data array[3] ;
// 構造体の大きさは何バイト?
printf( "%d\n" , sizeof( struct Data ) ) ;
printf( "%d\n" , sizeof( array ) ) ;

簡単なデータのバイト数の知識だけであれば、Dataの大きさは、3byte+4byteの 7byteと思うかもしれない。しかし、この考えだと、array の配列は、メモリ上に以下に並ぶと思うであろう。

n1,n1,n1が、array[1].nameの3byteをあらわすとする。
n0,n0,n0,p0,p0,p0,p0,n1,n1,n1,p1,p1,p1,p1,n2,n2,n2,p2,p2,p2,p2

しかし、最近のコンピュータでは、CPUクロック2GHz,メモリクロック1GHzといった速度で、 メモリの速度はCPUに比べて遅い。このため、CPUがメモリのデータを読み出す際は、 複数のbyte数を一括して読み込む。このデータの単位は32bitコンピュータであれば、 4byte単位であったりする。

ワード境界を考えない構造体要素の配置の場合
0行目:n0,n0,n0,p0,
1行目:p0,p0,p0,n1,
2行目:n1,n1,p1,p1,
3行目:p1,p1,n2,n2,
4行目:n2,p2,p2,p2,
5行目:p2,--,--,--,

この場合、array[1].pointを読み出そうとすると2行目と3行目の2回にわけて データを読み込むことになり、プログラムの速度が落ちてしまう。

このため、構造体の要素をメモリに保存する場合、4byte毎の「ワード境界」を またがってデータを配置しないようにするのが普通である。こういう メモリへの配置を「ワードアライメント」という。

ワード境界を考え、途中に空き(xx)を配置した例
0行目:n0,n0,n0,xx,
1行目:p0,p0,p0,p0,
2行目:n1,n1,n1,xx,
3行目:p1,p1,p1,p1,
4行目:n2,n2,n2,xx,
5行目:p2,p2,p2,p2

ということで、sizeof( struct Data ) は、8byteとなるのが普通である。 ただし、処理速度を犠牲にしてメモリ量を節約する必要がある場合には、 "#pragma …."といったプリプロセッサ命令で、隙間を詰めることもできる。

「ワード」とは、8bit = 1byte より大きいデータ単位で、16bitであったり、32bitであったりする。 機械語でプログラムを記述する際には、以下のように区別することが多い。
16bit = 2byte = ワード(WORD),対応する型:short int
32bit = 4byte = ダブルワード(DWORD)、対応する型:int,float
64bit = 8byte = QWORD、対応する型:double