link もっと前
   2009年 3月 22日 -
      2009年 3月 22日  
link もっと後

link 未来から過去へ表示(*)
link 過去から未来へ表示

日々

link permalink

ビットフィールド

今日は Java でビットフィールドを扱う方法を探していたのですが、やり方がわかりません。

ビットフィールド(C 言語)

#include <stdio.h>

union u {
        char c;
        struct _s {
                unsigned a:2;
                unsigned b:4;
                unsigned c:2;
        } s;
};

int main(int argc, char *argv[])
{
        union u v;

        v.s.a = 1;
        v.s.b = 0;
        v.s.c = 1;
        printf("v.c=%d(0x%x), v.s.b=%d(0x%x)\n",
                v.c, v.c, v.s.b, v.s.b);
        v.s.b = 10;
        printf("v.c=%d(0x%x), v.s.b=%d(0x%x)\n",
                v.c, v.c, v.s.b, v.s.b);

        return 0;
}

C だと上記のように構造体風に書けるんですが、Java だとどうすりゃいいんだろか。今は仕方ないのでシフトとビット演算でえっちらおっちら書いています。

シフトとビット演算

目的はある下位ビット(st ビット目とする)からある上位ビット(ed ビット目とする)を占めるビットフィールドを抜き出すことです。これはビットフィールドの書き換え、つまり上記の C でいうところの v.s.b = 10; のような処理をしたいときに必要です。

もう一つの目的はビットフィールドに入っている値を得ることです。これはビットフィールドを読み取り、つまり printf("%d", v.s.b); のような処理をしたいときに必要です。

まず st ビット以上を 1 で埋めたパターン(パターン A とする)を作ります。
作り方: 1 を st ビット左シフトして 1 を引くと、st ビットより下が 1 で埋まったパターンが得られますので、そのパターンをビット毎 NOT をするとパターン A が得られます。

次に ed ビット以下を 1 で埋めたパターン(パターン B とする)を作ります。
作り方: 1 を ed ビット左シフトして 1 を引くと、ed ビットより下が 1 で埋まったパターンが得られます。そのパターンに 1 を ed ビット左シフトした値をビット毎 OR すると、パターン B が得られます(※)。

パターン A とパターン B のビット毎 AND を取ると、st ビットから ed ビットまでが 1 で埋まったマスクが得られます。

ビットフィールドを保持している値とマスクをビット毎 AND すると、目的のビットフィールド以外を 0 で潰した値が得られます。

ビットフィールド内の値を得たい場合は、パターン B だけビット毎 AND して、その後 st ビット論理右シフトします。パターン A を AND しなくても結果は同じです。


ビットフィールド

例として st = 2, ed = 5 の状態を図示すると上記のようになります。

おそらく「何やってるんですか Java なら○○で一発ですよ!」ってオチがある気がしてならないので、もっと良いやり方があったらぜひ教えてくださいまし。

(※)1 を ed + 1 ビット左シフトして 1 を引く方法は正常に計算できない場合があります。ed と変数のビット長が等しい場合、(変数のビット長 + 1) ビットの左シフトが起きます。C や Java では変数のビット長を超える左シフトの結果は不定のため、得られるパターンも不定となります。

[編集者: すずき]
[更新: 2009年 3月 26日 01:08]
link 編集する

コメント一覧

  • すずき 
    間違っていたので訂正。
    Javaでビット長を超える左シフトの結果は不定ではなく、シフト量の下位数ビットのみ有効になる、が正解です。

    intに対する左シフトの場合は下位5ビット、つまり0〜31まで、
    longに対する左シフトの場合は下位6ビット、つまり0〜63までシフトできます。
    例を挙げると、intに対する32ビットシフト=0ビットシフトです。

    参考: Java Language Specification, Third Edition, chapter 15(expressions), 15.19 Shift Operations 
    (2011年03月03日 09:27:08)
open/close この記事にコメントする



link もっと前
   2009年 3月 22日 -
      2009年 3月 22日  
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 11/11 11:44

カレンダー

<2009>
<<<03>>>
1234567
891011121314
15161718192021
22232425262728
293031----

最近のコメント 5件

  • link 19年09月01日
    すずき 「私も正直びっくりです。間違って違う製品を...」
    (更新:09/04 23:39)
  • link 19年09月01日
    hdk 「車向けの製品の中でも、車載コンピューター...」
    (更新:09/02 23:20)
  • link 19年07月18日
    hdk 「あっ、AAMはマニュアルのオペレーション...」
    (更新:07/25 00:02)
  • link 19年07月18日
    すずき 「AAM(ASCII Adjust AX ...」
    (更新:07/24 22:22)
  • link 19年07月18日
    hdk 「加算減算は符号のありなしどちらも命令が同...」
    (更新:07/24 07:25)

最近の記事 3件

link もっとみる
  • link 19年11月07日
    すずき 「[独自の apt サーバー - その 6 - ソースコードパッ] ...」
    (更新:11/11 11:44)
  • link 19年08月29日
    すずき 「[独自の apt サーバー - その 5 - 複数のセクション] ...」
    (更新:11/08 00:41)
  • link 19年08月13日
    すずき 「[独自の apt サーバー - その 4 - まとめ] 独自の a...」
    (更新:11/08 00:41)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報