パスワードを忘れた? アカウント作成
13004663 journal
日記

ttの日記: オレオレビットフィールドを作る 4

日記 by tt

人生初のAdvent Calendarをしてみんとしてなんとなく久々に日記など。
C言語 Advent Calendar 2016 の6日目、らしい。

Cの世界にはビットフィールドというのがある。もともとハードウェアレジスタを操作するために作られたと思われるが、今やメモリ削減のために使われている感がある(ex. webkit)。
どうしてこうなったか…というとまあ規格上いろいろと自由度と不自由度がありすぎて、エンディアンとかintの大きさとかによって「実際の」ビットの位置がずれてしまい、移植性のあるコードを書くのがめんどくさいからである。
ハードウェアを触るなんてマシン固有だからどーでもいいじゃん、というのはあるんだが、x86でもx86-64でも動いてほしいとか、ARM BEとARM LEで~とか、いろいろあるのである。

前振りが長くなった。さて本題。

ビットフィールド使えないとなるとレジスタ操作系のコードはこういうのになる
  int reg = MMIO_REG_READ(COMMON_REG_ADDR);
  int busy = (((reg >> STATUS_BIT_POS) & STATUS_BIT_LEN) == STATUS_BUSY);
わかりやすい。というか超べたべただ。

マクロなりなんなりで
  int busy = (extract(reg, STATUS_BIT_POS, STATUS_BIT_LEN) == STATUS_BUSY);
なんて書くのも可能だし、マクロの定義を適度にいじってintのサイズ違いに対処とかもできそうだ。

と、ここまではよく見るんだけど、最近
  extract(reg, STATUS_BIT_POS : STATUS_BIT_LEN)
みたいな書き方があるのを知った。

どーやってるんだろうとおもったら、こういう感じらしい
  # define GETPOS(field) (0 ? field)
  # define GETLEN(field) (1 ? field)
  # extract(reg, field) (((reg)>>GETPOS(field))&((1uGETLEN(field)-1))
そう、三項演算子を使うらしい。

で、これの利点だけど…ハードウェアの仕様書とかではビットフィールドの記述に「:」を使うのは多いため、見た目がわかりやすい、ということ以外にあんまり思い浮かばなかった(笑)。C++はともかく、Cでは三項演算子やラベル名以外で:を使うというのはあんまりないので、他より目立たせることができる、というのもあるだろうか。

あんまり意味がないけど、まあ、面白いのでご紹介、ということで。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

吾輩はリファレンスである。名前はまだ無い -- perlの中の人

読み込み中...