ホーム » スタッフ » 斉藤徹 » ワード境界とビットフィールド

2009年11月
« 10月   12月 »
1234567
891011121314
15161718192021
22232425262728
2930  

最近の投稿(電子情報)

アーカイブ

カテゴリー

ワード境界とビットフィールド

構造体の説明の後半として、メモリの使用量と関係深いワード境界とビットフィールドの説明を行う。 最初に、主記憶の不足とプログラムの関係として、仮想メモリとメモリ不足時にハードディスクアクセスが多発し、スピード低下について述べる。

ワード境界

struct A {
   char name[ 3 ] ; // イニシャルと点数の構造体?
   int  point ;
} a[ 4 ] ;
境界無視 境界配置
|NNNP|   |NNNx|    N:name
|PPPN|   |PPPP|    P:point
|NNPP|   |NNNx|
|PPNN|   |PPPP|
|NPPP|   |NNNx|
|PNNN|   |PPPP|
|PPPP|   |NNNx|
|PPPP|

CPUに比べて、主記憶の速度は遅いため、メモリアクセスは必要最小限にしたい。 しかしながらワード境界を無視すると、a[0].point の取得には、2回のメモリアクセスが 発生するため、処理速度が低下する場合がある。 このため、name 3文字の後ろに1byteの空きを設けて、ワード境界をまたがらない様に 構造体の要素を配置するのが一般的。

この話の前に、char=8bit=1byte=0..255(-128..0..127),32bitCPUなら、 int=32bit=4byte=-2^31..0..2^31-1といった復習を簡単に行った。

メモリインタリーブとよばれる方式を使うと、 ワード境界があっても最小限のメモリ参照で済むが、ハードウェアが複雑化する。 情報処理技術者試験を受けるのであれば、インターリーブも理解しておくこと。

ビットフィールド

struct YMD {
   int  year ;
   int  month ;
   int  day ;
} ;

といった構造体では、12byte のメモリを使用するけど、メモリ使用を減らすには、 year=0..2047,month=0..15,day=0..31と考えれば、20bitで十分。 メモリの使用量を減らすために、year , month , day を1つのint型で覚えるには?

ymd = year *10000 + month*100 + day ;
printf( "月=%d" , (ymd % 10000) / 100 ) ;

という方法もあるけど、2進数として年月日を覚えるのであれば、

// YYYYYYYYYYY000000000
// or         MMMM00000
// or             DDDDD
ymd = (year << 9) | (month << 5) | day ;
printf( "年=%d" , ymd >> 9 ) ;
printf( "月=%d" , (ymd >> 5) & 0x0F ) ;
printf( "日=%d" , ymd & 0x1F ) ;

とすれば、int 型で、年月日を必要最小限のbit数で保存できる。 しかしながら、2進数演算は分かりにくいので、以下のようなビットフィールドを使えば簡単。

struct YMD {
   unsigned int  year  : 11 ;
   unsigned int  month :  4 ;
   unsigned int  day   :  5 ;
} ;