構造体のワード境界
今日は、構造体を使ったプログラミングの演習。 単純な演習だけでは、来週に研修旅行を予定している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