C言語関係掲示板

過去ログ

No.1002 ビット演算のマスク処理

[戻る] [ホームページ]
No.918

ビット演算の演習問題について
投稿者---KAZ(2003/12/30 12:20:21)


ビット演算の演習問題の2ばんの解答の以下の行のマスク処理の部分が理解できません。

printf( "%#x ---> ", dt );
for ( i = len - 1; i >= 0; i-- ){
/* ビットの表示 */
printf( "%u", ( dt >> i ) & 0x0001 );

dtはunsigned int で4バイトつまり32ビットです。
このプログラムではiビットシフトしてそれを0x0001でマスクしているようなのですが、0x0001は16ビットですよね。以下に私の疑問を示します。
仮に (de >> 1) の時点で以下のバイナリーナンバーがあるとします。

00000000 00000001 00000000 10000001

これに対して0x0001でAND演算ということなので

0x0001 ーー> 0000 0000 0000 0001

00000000 00000001 00000000 10000001
******** ******** 00000000 00000001
----------------------------------------
00000000 00000001 00000000 00000001

このように最初の16ビットがマスクされないように思えるんですが。。
実行結果が正しくでるので私の考えがどこかで間違っているみたいです。
どなたか分るかた間違いを指摘してください。

No.919

Re:ビット演算の演習問題について
投稿者---YuO(2003/12/30 12:48:10)


>このプログラムではiビットシフトしてそれを0x0001でマスクしているようなのですが、0x0001は16ビットですよね。以下に私の疑問を示します。

0x0001はint型の値を持ち,intが32bitであれば32bitの幅を持つ値です。

故に,
>これに対して0x0001でAND演算ということなので
>0x0001 ーー> 0000 0000 0000 0001
>00000000 00000001 00000000 10000001
>******** ******** 00000000 00000001
>----------------------------------------
>00000000 00000001 00000000 00000001

ではなく,
0000 0000 0000 0001 0000 0000 0000 0001 /* 0x10001 */
0000 0000 0000 0000 0000 0000 0000 0001 /* 0x0001 */
---------------------------------------
0000 0000 0000 0000 0000 0000 0000 0001 /* 0x00000001 */

となります。


>このように最初の16ビットがマスクされないように思えるんですが。。

数値の幅はあくまで型の幅です。
どのように表記しようと,int型の数値は常にint型の幅を持ちます。


No.920

Re:ビット演算の演習問題について
投稿者---kaz(2003/12/30 19:50:18)


すばやいレスありがとうございます。

>
0000 0000 0000 0001 0000 0000 0000 0001 /* 0x10001 */
0000 0000 0000 0000 0000 0000 0000 0001 /* 0x0001 */
---------------------------------------
0000 0000 0000 0000 0000 0000 0000 0001 /* 0x00000001 */

>となります。

>数値の幅はあくまで型の幅です。
>どのように表記しようと,int型の数値は常にint型の幅を持ちます。

とのことですが、0x0001が32ビットにもなりうるというのがまだ理解できません。というのも私はこの0x以下の0001をhexadecimal表示と思っています。ちがうのでしょうか?hexadecimalの場合、4ビットを0からfまでで表示しますよね。仮に0xff0fというのがあった場合、これは

0xff0f --> 1111 1111 0000 1111

と考えることはできるのですが、もしunsigned int のように32ビットの
型と演習問題の回答にあるように&演算させた場合、

0xff0f --> 11111111 11111111 00000000 11111111

となるのでしょうか?でもfは10進数でいうと15であって2進数でいうと1111ですよね。fが8ビットにもなりうるというところが理解できません。もう少しつっこんだ説明をお願いできますでしょうか?どうかよろしくおねがいします。




No.921

Re:ビット演算の演習問題について
投稿者---あかま(2003/12/30 20:55:10)


>fが8ビットにもなりうるというところが理解できません。
いや、ならないです。

0xf
は10進で15です。
0x0f
も10進で15です。
0x00f
0x000f
0x0000f
も10進で15です。したがって

0x0001
と16ビットのように書こうが
0x00000001
と32ビットのように書こうがおなじ数値を表します。
つまり同じ数字を表すのなら0いっぱい書かなくてもいいでしょ?って話なだけです。
桁が足りないときは0が詰まってると考えてください。

>数値の幅はあくまで型の幅です。
>どのように表記しようと,int型の数値は常にint型の幅を持ちます。

これがすべてです。
桁数分書いたほうが分かりやすいかもしれませんが、intならintで処理系によって桁数が違うのでそれもまた難しいですね。

No.922

Re:ビット演算の演習問題について
投稿者---ともじ(2003/12/30 22:49:33)


YuOさん、あかまさん、いつもご回答ありがとうございます。

>桁数分書いたほうが分かりやすいかもしれませんが、intならintで
>処理系によって桁数が違うのでそれもまた難しいですね。

このホームページの元になる資料を作ったときに、intサイズ2バイト
のコンパイラを使っていたため、ホームページ自体が、intサイズ2バイト
を基準にしています。intサイズ4バイトが主流になった現在では、
4バイトに直した方がよいのかもしれませんが、初心者の方に、あくまでも
intサイズは処理系依存だということを知っていただいた方がいいと思い、
そのままにしてあります。

ですから、この演習の解答例では 0x0001 でマスクしています。
ただし、シフトは
        len = sizeof(dt) * CHAR_BIT;
        for ( i = len - 1; i >= 0; i-- )
                printf( "%u", ( dt >> i ) & 0x0001 );

のように、intサイズ4バイトでも対応できるようにしています。

もっとも、この解答例のページからもリンクしていますが、
http://www.bohyoh.com/CandCPP/FAQ/FAQ00018.html
にあるように、intサイズ12ビットのような特殊な処理系には対応して
いません。ただ、演習問題で、ここまで特殊な処理系のことを考える
必要はないと考えています。


No.923

ありがとうございます。
投稿者---KAZ(2003/12/31 11:59:20)


みなさん、丁寧な解説ありがとうございます。おかげさまでようやく理解することができました。またこの掲示板を利用させてもらうかもしれません。その時はまたどうかよろしくお願いします。