ttの日記: オレオレビットフィールドを作る 4
人生初の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では三項演算子やラベル名以外で:を使うというのはあんまりないので、他より目立たせることができる、というのもあるだろうか。
あんまり意味がないけど、まあ、面白いのでご紹介、ということで。
マクロの引数を二回評価している時点でクソすぎ (スコア:0)
副作用のある式を渡されたらどうなるか少しでも考えたのかこのアホは。
Re:マクロの引数を二回評価している時点でクソすぎ (スコア:2)
前半に、このマクロ関数が便利な状況という限定があって、
そのうえで、引数に副作用のある「式」を、ってどういう
コードを想定してるの?
Re:マクロの引数を二回評価している時点でクソすぎ (スコア:1)
Re: (スコア:0)
標準ライブラリにすら getc・putc というやつがあるのに
そんなこと言ってもしょうがないと思うの…