• ベストアンサー

ビット演算について

いつもお世話になります。 ビット演算について教えて下さい。 unsigned char buf1[1]=0x5a unsigned char buf1[2]=0x04 unsigned char buf1[3]=0x38 5a0438(16)を3バイトの値を12ビットずつの整数で得るにはどうしたらいいのでしょうか? 2進数表記では、 5A | 04 | 38 01011010 | 00000100 | 00111000 12ビットずつとは、 010110100000 010000111000 と区分し、10進数の整数値で得たいです。どのようにすればよいでしょうか? また、0x5Aなどの16進数を2進数のビットで考えるときに、 01011010を下位4ビットを10進数整数を得るにはどうしたらよいのでしょうか? 上記2点、どうぞよろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

論理演算とビットシフトの組み合わせてで実現できます。 とその前に、10進数整数を得ると書かれてますがコンピュータの整数値は基本的に2進数で内部処理されます。 10進数は表示時にprintf関数がワザワザ10進数に変換しているのであって、内部では2進数な事を忘れないでください。 intもshortもcharも全て2進数(binary)です。 >unsigned char buf1[1]=0x5a >unsigned char buf1[2]=0x04 >unsigned char buf1[3]=0x38 short uppper12bit = (buf[1] << 4) | (buf[2] >> 4); short under12bit = ((buf[2]&0x0f)<<8) | buf[3]; printf("上12bit=%d 下12bit=%d\n",uppper12bit,under12bit); >また、0x5Aなどの16進数を2進数のビットで考えるときに、01011010を下位4ビットを10進数整数を得るにはどうしたらよいのでしょうか? unsigned char under4bit = buf[1] & 0x0f; printf("上4bit=%d\n",under4bit); 16進数も2進数と書き方が違うだけで同じものです。これといった複雑なことが行われているわけではありません。C言語は16進数で代用できるので2進数が言語上存在しないのです。

the-ai
質問者

お礼

丁寧な回答ありがとうございます。 大変助かりました。 ビット演算をもう少し勉強します。 本当に有難うございました。

その他の回答 (2)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3

php504 さんの回答で気になったのは、格上げがあるのでキャストの必要がないだろうという点と、シフトとビットアンドの優先度の違いですね^^; the-ai さんの質問で気になったのは、添え字は 0 からにしたほうが自然だろうという点と、バイト順を意識してほんとにしたいことをしているのか、という点です^^ ちょっとした老婆心ですが(笑)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

単に3バイト(24ビット)を12ビットに分けるだけなら (unsigned short)buf[1] << 4 | buf[2] >> 4; buf[1]を4ビット左へシフトして空いた4ビット分にbuf[2]を右に4ビットシフトした値を入れる (unsigned short)buf[2] & 0x0F << 8 | buf[3]; buf[2]の下位4ビットを左に8ビットシフトして空いた8ビットにbuf[3]を入れる 下位4ビットだけにしたいなら 0x5A & 0x0F;

the-ai
質問者

お礼

早速の回答ありがとうございます。 助かりました。 ビットシフト/演算をもう少し勉強します。 有難うございました。

関連するQ&A

  • ビット演算で00000001と1の頭に0を付ける?

    https://www.grapecity.com/japan/powernews/column/clang/019/page02.htm ビット演算子 表1にCのビット演算子を掲げておきます。ビット演算とは言っても、扱う値はバイト単位などCの一般的な整数のデータ型です。ビット演算子は、それらの値をビット単位で計算します。 ビットシフト演算(<< >>)~2倍と1/2 例えばunsigned char型の1は、2進数では"00000001"という形のビット列(ビットパターン)になります。これを1桁左にずらす(シフトする)と"00000010"となります。ずらしてあふれた左端の0は消え、空いた右端には0が入ります。 "00000001"は10進数の「1」、"00000010"は10進数の「2」です。つまり、ビット列を左に1桁シフトすると値は2倍になるのです。 -----------------------------------------  以上ですが、C言語の、ビット演算の解説の抜粋です。ビット演算はまだ覚えたてですが、"00000001"整数1の頭にわざわざ、0を沢山 つける目的は何なのでしょうか!?  よろしくお願いします。

  • ビット演算について

    ビット演算について質問なんですが、例えば以下の16ビットのデータ(値は変わる)を 0111 1011 1000 0000 を 0000 0001 1101 1110 や 1111 1111 0000 0000 を 0000 0000 1111 1111 上位にあるビットを下位ビットに、下位にあるビットを上位ビットに に逆に入れたいんですが やり方が分からなく質問しました よろしくお願いします

  • ビット演算を使えば出来ますか?

    あるchar型の変数の各ビットを二つずつにして別の変数にしまいたい場合どういうプログラムを作ればいいでしょうか? char型の変数 data1 = 0x51があるとします。 2進数で表すと[01010001] になります。 これを別のchar型の変数に data2=[00110011], data3=[00000011]というふうにしてしまいたいのです。 なにぶん素人なものでうまく説明できませんが各ビットを二つにして横に伸ばすイメージです。 0→00 1→11 となります。 data1=0x33だと[00110011]ですから作りたいデータは data2=[00001111],data3=[00001111]です。 data1=0x12だと[00010010]ですから作りたいデータは data2=[00000011],data3=[00001100]です。 for文とビット演算をつかってdata1からdata2とdata3を作れそうな気はしますがよくわかりません。 説明が分かりにくくて申し訳ありませんが、どなたか教えていただけないでしょうか?

  • C言語の配列の扱い

    次のような配列bufと変数dataを宣言して bufの中身をdataにコピーしたいのですが、 buf[0]のみで、buf[1]の値が入りません。 具体的には、buf[0]には16進数で0x3f、 buf[1]には0x3aが入っていて、 dataの値を0x3a3fにしたいのです。 教えてください。 ***************************** unsigned char buf[2]; unsigned short data; data = (unsigned short)*buf; *****************************

  • ビット演算について

    以下のプログラムを作成して、int型、char型、long型のAND演算・OR演算の結果の違いを見ました。 実行結果からchar型だけ結果の表示の仕方が他と異なっています。 一般的に、バイト数では、 char(1バイト) < short(2バイト) < int(4バイト) のはずなのに、出力結果は、 char(0xffffffff) > short(0xff) = int(0xff) となっていて、charが一番大きく?、shortとintが同じ結果? のようにみえてしまいよくわかりません。 私は、ビット演算が苦手なので、根本的に考え方が間違っているのかも しれませんが、どうしてこのような出力結果となるのか教えてください。 プログラム #include <stdio.h> #include <stdlib.h> int main() { int xi = 0x7F, yi=0x80; int stri1 = xi&yi; int stri2 = xi|yi; printf("** int **\n"); printf("%p\n",stri1); printf("%p\n\n",stri2); char xc = 0x7F, yc=0x80; char strc1 = xc&yc; char strc2 = xc|yc; printf("** char **\n"); printf("%p\n",strc1); printf("%p\n\n",strc2); short xl = 0x7F, yl=0x80; short strl1 = xl&yl; short strl2 = xl|yl; printf("** short **\n"); printf("%p\n",strl1); printf("%p\n\n",strl2); return(0); } 出力結果 ** int ** 0x0 0xff ** char ** 0x0 0xffffffff ** short ** 0x0 0xff

  • ビット演算について

    ビット演算ができないダメグラマーです。 10101010 C言語でバイト値の3ビット目の値が0の時は1に1の時は0(ビットを反転)にするにはどのように書くのでしょうか?

  • ビット演算子について

    ビット演算子のことがよく分かりませんので、結果の求め方を教えてください。ちなみに16進数、2進数などは分かります。 〈例〉(1) 0xf0 & 0xaa     (2)~0x55

  • ビット演算子について

    あるプログラムの中で下記のようなif文の記述を見かけました。 どういう計算をしてif文の判定を行っているのでしょうか。 (1)256を2進数に変換して → 100000000 (2)0x00000004を2進数に変換して → 100 (3)100000000 & 100 のビットAND演算を行う そもそも(3)で100000000 と 100 では桁数が違うけどどうやって両者でビット演算するので しょうか。100を 000000100というように0を補完して計算すればよいのでしょうか。 その場合、100000000 & 000000100 → 000000000(2進数) → 0(10進数) となりif文の中には入らないことになると思います。 if(256 & 0x00000004 != 0)

  • php と C# の ビット演算

    PHPでビット演算をしていますが、 PHPでたとえば、 c = a >> b でビット演算した値と、 C#で演算した値と aの値を大きくした場合、 4000000000以上? は結果が違ってきます。 C#とPHPではビット演算のアルゴリズムが違うのでしょうか? よろしくお願いします。

    • ベストアンサー
    • PHP
  • ビット演算について

    4バイトのデータの下位4ビットのみ変更したいとします。 int nInformation = hoge; // <-なんらかのデータ int nFlg = 0x06; // <- nInformationの下位4ビットを書き換えるデータ この場合、どうやって書き換えるのがスマートなやり方でしょうか。 とりあえず、 nInformation = ((nInformation&0xFFFFFFF0)|nFlg); としてみたのですが、あんまりうまい気がしません。 よろしくお願いします。

専門家に質問してみよう