LoginSignup
17
16

More than 5 years have passed since last update.

[C/C++]シフト演算だけで特定のbitを読み出す

Posted at

はじめに

学校で教科書として使っているCQ出版社の「組み込みソフトウェア開発スタートアップ」(デザインウェーブマガジン編集部 編)という本があるのですが、この本の50ページに「シフト演算だけで値を読み出す場合」として以下のようなサンプルコードが記されています。

#define bit(x, n) ((x << (8 * sizeof(int) - n - 1)) >> (8 * sizeof(int) - 1))

使い方としては、xというビット列からn番目だけを抜き取って読む、ということだと思います。しかしこれ、ぱっと見何をしているのかよくわからないので分解しつつ見ていきましょう、というお話です。

早速解読してみる

今回はxとして二進数で「10000101」を、nとして「2」を使ってみます。最も右のbitが0番目という風に数えます。

まずはここの部分から。sizeof(int)をとりあえず4bytesと解釈しましょう。うちのclangがそういう仕様だったもので。

(x << (8 * sizeof(int) - n - 1))

こういうことなので、何bit左にシフトすべきか計算してみましょう。

8 * sizeof(int) - n - 1 = 8 * 4 - 2 - 1 = 29

ふむなるほど。ということはxは左に29bitシフトされて、こんな感じになります。縦棒から右がシフトされた分です。桁数はsizeof(int)の桁数で固定されますので、今回の場合全体として4bytes=32bitとなります。つまり、それ以上の桁はあふれていってしまうわけですね。

101|00000000000000000000000000000

では次の部分を。

(8 * sizeof(int) - 1)

これを計算した分だけ右にシフトすればいいわけですね。となると

8 * sizeof(int) - 1 = 8 * 4 - 1 = 31

ですね。改めて右に31bitシフトしてみましょう。今度は縦棒から左がシフトされた分です。

0000000000000000000000000000000|1

確かに特定のbitを読み取ることができることができました。しかしよくこんなトリッキーな計算方法思いつきますね...

int型の大きさは処理系によってまちまちです。しかしあくまで整数値の読み出しなので、sizeof演算子を使ってどんな環境でも動くようにしてあるんですね。恐れ入りました...

17
16
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16