• ベストアンサー

C++ ビット演算

ビット単位でのフラグ管理の方法を調べています。 その上で何点か疑問が出てきましたので質問させて頂きます。 ・10進数を2進数に変換する方法は2で割って余りを並べていくというものですが、別なやり方(標準関数など)はないのでしょうか。 ・unsigned char EightFlag = NULL; と = 0 は同じ意味でしょうか。 ・「a |= b」、「a ^= b」、「a ~= b」 と記述した場合、それぞれどのような判定が行われているのでしょうか。(真理値表というものをみたのですが意味がよくわかりませんでした) 以上です。 回答よろしくお願いします。

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

  • ベストアンサー
  • black2005
  • ベストアンサー率32% (1968/6046)
回答No.4

No.1です。 お礼の内容が良く理解できないのですが・・・^^; 16進数で表現すれば、内部的にはbitを操作してるのと同じ事です。 例えば1byte(8bit)単位では 0x01:B00000001 0x02:B00000010 0x04:B00000100 0x08:B00001000 ・ ・ 0x80:B10000000 ※BはBinary(2進数)であることを示す 以下、これを応用 unsigned char EventFlg = 0 ; //8bitの変数宣言と初期化 EventFlg |= 0x01 ; //0x01とOR(論理和)することによりEventFlgのB0(1bit目)がON(1になる) EventFlg |= 0x10 ; //0x10とOR(論理和)することによりEventFlgのB4(5bit目)がON(1になる) EventFlg |= 0x0F ; //0x0FとOR(論理和)することによりEventFlgのB0~B3(1bit目~4bit目)がON(1になる) EventFlg &= 0xFE ; //0xFEとAND(論理積)することによりEventFlgのB0(1bit目)だけをOFF(0になる) 上記が理解出来れば、目的は達するはずです。

ShimantoGa
質問者

お礼

再度のご回答有難う御座います。 >お礼の内容が良く理解できないのですが・・・^^; 上手く説明できず申し訳ありません。 >16進数で表現すれば、内部的にはbitを操作してるのと同じ事です。 基本10進、2進でフラグ管理を行おうとしていました。(A~Fが出てくるとややこしく思えたため) >0x01:B00000001 ~EventFlg |= 0x01; ~ 成程、こういう記述の仕方をするんですね。 16進数で代入というのは慣れていませんが、フラグ管理の方法は理解できました。 誠に有難うございます。

その他の回答 (3)

  • precog
  • ベストアンサー率22% (966/4314)
回答No.3

>・10進数を2進数に変換する方法は2で割って余りを並べていくというものですが、別なやり方(標準関数など)はないのでしょうか。 10進数とはなんのことでしょうか? 10進文字列? であればscanf系の%dとかが基本ですよね。 >・unsigned char EightFlag = NULL; と = 0 は同じ意味でしょうか。 それはNULLの定義によります。大概の人は0と定義すると思いますけど、処理系で保証されているわけではありませんので、デバッグの際には必ず追いかけます。 >・「a |= b」、「a ^= b」、「a ~= b」 と記述した場合、それぞれどのような判定が行われているのでしょうか。(真理値表というものをみたのですが意味がよくわかりませんでした) 判定とは? それらは全部代入演算子ですけど。 真理値表がわからないなら、真理値表を勉強するしかないです。

ShimantoGa
質問者

お礼

回答有難う御座います。 >10進数とはなんのことでしょうか? 10進文字列? であればscanf系の%dとかが基本ですよね。 変換指定子ですか、失念しておりました。有難うございます。 >処理系で保証されているわけではありませんので~ 同じC++でもCPUやコンパイラによっては値が変わるということでしょうか。 >判定とは? それらは全部代入演算子ですけど。 先に記述しましたがどうにも10進数の考え方が抜けきらないものでして、a = a + b のような一文で書ける処理ではないのでは、と思ってしまいます。 真理値表を学ぶと同時に認識を変えていこうと思います。 >真理値表がわからないなら、真理値表を勉強するしかないです。 宜しければ確認させて頂きたいのですが、 b = 11 と c = 01 で論理積であれば //2ビット目 if(1 == 0){ //False a = 1; }else{ a = 0; } //1ビット目 if(1 == 1){ //True a = 1; }else{ a = 0; } 結果:a = 01 という読み方であっていますでしょうか。

  • chie65535
  • ベストアンサー率43% (8520/19368)
回答No.2

>・10進数を2進数に変換する方法は2で割って余りを並べていくというものですが、別なやり方(標準関数など)はないのでしょうか。 「ビット単位でのフラグ管理」には「10進」「2進」は不要な概念です。 なので、やり方もクソもありません。単に #define IS_RED 1 #define IS_BLUE 2 #define IS_YELLOW 4 #define IS_GREEN 8 とか #define O_RDONLY 0 #define O_WRONLY 1 #define O_RDWR 2 #define O_ACCMODE 3 #define O_DENYALL 0x10 #define O_DENYWRITE 0x20 #define O_DENYREAD 0x30 #define O_DENYNONE 0x40 #define O_NOINHERIT 0x80 #define O_CREAT 0x0100 #define O_TRUNC 0x0200 #define O_EXCL 0x0400 #define O_APPEND 0x0800 #define O_CHANGED 0x1000 #define O_DEVICE 0x2000 #define O_TEXT 0x4000 #define O_BINARY 0x8000 とかの「定義」が存在するだけです。 「値が各ビットに対応していれば良い」ので、それが10進だろうが8進だろうが4進だろうが2進だろうが、どういう表記であっても関係ありません。 >・unsigned char EightFlag = NULL; と = 0 は同じ意味でしょうか。 「同じ意味かどうかは不明」です。 「NULLがどう定義されているのか不明」なので、同じ意味かどうかも「不明」です。 >・「a |= b」、「a ^= b」、「a ~= b」 と記述した場合、それぞれどのような判定が行われているのでしょうか。(真理値表というものをみたのですが意味がよくわかりませんでした) 「判定」など行われません。 単に「ビット演算」と「代入」が行われるだけです。 「判定」が行われるのは「式を『判定式』に使用した場合」のみです。 因みに「a |= b」は「a = a | b」と同じ意味、「a ^= b」は「a = a ^ b」と同じ意味で、aとbをビット演算(それぞれ、論理和、排他的論理和)して、結果をaに代入します。また「a ~= b」は構文エラーなのでコンパイル出来ません。 >真理値表というものをみたのですが意味がよくわかりませんでした 真理値表が理解できない場合、ビット単位でのフラグ管理は絶対に理解出来ません。 真理値表について学び、真理値表が理解できた時に、もう一度質問して下さい(早い話が「お話にならない」って事)

ShimantoGa
質問者

お礼

回答有難う御座います。 >「ビット単位でのフラグ管理」には「10進」「2進」は不要な概念です。 表記上は不要かもしれませんが、概念として理解している必要はあるのではないのでしょうか。 0、1信号(機械語)は2進数表記ですし、フラグという意味で0(False)、1(True)という考え方は必要な気がするのですが。(間違っていたらすみません) >「NULLがどう定義されているのか不明」なので、同じ意味かどうかも「不明」です。 NULLの定義が不明というのは初耳でした。 if文で NULL を入れた変数と 0 が入った変数を比較すると True の結果が返ってきたため、疑問に思っていました。 >「判定」など行われません。 ビット演算子を調べると、ANDやORなどの記述が見られたため、単純な計算ではないのかと考えていました。 例えば論理積の場合:a = b & c; if(b == c){ //判定 a = 1; }else{ a = 0; } のような処理が内部で走っているものと思っていました。

ShimantoGa
質問者

補足

記述に間違いがありました。 if(b == c){ ではなく if(b == 1 && c == 1){ です。 上記に2つのお礼に関して、大変申し訳ありませんでした。

  • black2005
  • ベストアンサー率32% (1968/6046)
回答No.1

質問内容からして、基本的な論理式を理解されていないと思われます。 ビット操作を行う前に、まずは論理式を勉強しませう。 >10進数を2進数に変換する方法 論理式が解れば、こんな質問は出てこないはず。 10進→2進変換など不要、全く無意味です。

ShimantoGa
質問者

お礼

回答有難う御座います。 >論理式が解れば、こんな質問は出てこないはず。 論理式について調べてみました。 確認させて頂きたいのですが、真理値表はあくまで1ビット毎の計算結果であるという理解でよろしいでしょうか。 >10進→2進変換など不要、全く無意味です。 おっしゃる通り、EightFlag = 0 とすれば変換の必要もなく 00000000 ですし、 = 255 とすれば 11111111 でしかありません。 しかし、 EightFlag = Henkan(255); のような記述ができれば、、デバッグ時に理解しやすいと思いました。 ビット演算を学ぶ上でソースの見やすさを優先したかったのです。(Henkan()は10進数を2進数に変換する関数とお考えください)

関連するQ&A

  • ビット演算について

    いつもお世話になります。 ビット演算について教えて下さい。 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点、どうぞよろしくお願い致します。

  • 8個のビットを1バイトとして扱う方法

    1バイトをビット扱いする方法は、 union un_p1dr { unsigned char one_byte ; struct { unsigned char b7:1 ; unsigned char b6:1 ; unsigned char b5:1 ; unsigned char b4:1 ; unsigned char b3:1 ; unsigned char b2:1 ; unsigned char b1:1 ; unsigned char b0:1 ; } bit ; } ; #define pt_da_p1dr (*(volatile union un_p1dr *)0xffffd0) と宣言すれば、pt_da_p1dr.bit.b7 = 1 ;の様にビット扱いが出来ます。 この反対を行える宣言方法は、あるでしょうか? つまり、任意の1ビットを8ビット集め、プログラムでバイトにてアクセスしたいのですが・・・・ ARMなどは、ビットの扱いが容易に可能です。しかし、CPUの周辺関係事情より、バイトでのアクセスが 可能なように、ハード割り当てが出来ません。 従って、現在は、プログラムにて、ビットを集め、バイトにして、アクセスしています。 なにか良い宣言方法があれば、ご伝授していただけないでしょうか? 宜しくお願いいたします。

  • ビット演算で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を沢山 つける目的は何なのでしょうか!?  よろしくお願いします。

  • VC++6.0でC言語の基本データ型のビット長と範囲をしりたいです

    VC++6.0を使用しています。コマンドラインを使い勉強しているのですが、基本データ型のビット長と使える数の範囲を知りたいです。 たとえば、int型だと32ビットで-32767から32767の範囲の数を扱えるとかを知りたいです。コマンドライン上から調べることはできないのでしょうか? ネットでも書いてあるところがあるならいいのですが、できれば自分の手で調べる方法を見つけたいのです。 ちなみに char, unsigned char, int, unsigned int, short int, unsigned short int, long int unsigned long int, float, double, long doubleなどが知りたいです。 方法を知っている方教えてください。よろしくお願いします。

  • C言語で確保できるビットの桁数

    C言語でビット単位でデータ操作する際に、確保できるビットの桁数はたとえば以下のような例の場合 unsigned char bit; 1バイト(=8ビット)なので8桁ということは勉強しました。 ここで、たとえば計算でビットの桁数を100桁用意したい場合 以下のように32*4桁という風に分ける方法しかないのでしょうか? unsigned int bit[4]; できれば一つの変数で済ませたいのですが、何か良い方法をご存知の方いらっしゃいましたらよろしくお願いします。

  • C言語のビットフィールドで分からないところがありま

    union UNION { struct { unsigned int a :(32-8-5); // この部分 unsigned int b :8; unsigned int c :5; }BIT; }; 上記の「この部分」と書いてある行の意味を教えてください よろしくお願いします

  • C言語の条件式での~(チルド)について

    C言語に関しての質問です。 以下のようなプログラムでは変数bをキャストした場合と しない場合で条件式の判定結果が違います。 変数bはもともとunsiged char型なのでキャストは不要だと 思ったのですが、なぜ結果が違うのでしょうか? (条件式if(a != ~b)の判定結果も偽になることを期待していました。) unsigned char a; unsigned char b; a = ~0x98; b = 0x98; if(a != ~b) { printf("こっちは入る"); } if(a != (unsigned char)(~b)) { printf("こっちは入らない"); }

  • ビット演算のやり方

    a=10101,b=11011,c=10001という文字があり まずこのa,b,cを一列に並べ d=101011101110001という文字列にした後に、これを5bit単位にわけ その中の下位4bitを使い並べるとした時どうしたらいいでしょうか? 5bit単位とは次のように分けます d=10101 11011 10001 それで分けた5bitごとに下位4bitを適用するとして、 dは0101  1011  0001となり 結果をe=010110110001とするにはどうしたらいいでしょうか?

  • c言語で乱数を扱うときの

    乱数を初期化するために srand((unsigned)time(NULL)というのを使いますが これはどういう意味を表してるんでしょうか? timeは1970年から経過した時間を表していることは分かりますし unsignedは符号ビットをなくして表せる数を倍にしてることも分かりますが、 NULLって何のために書いてあるのでしょうか?

  • 配列のビット設定方法

    以下のようにビットを設定する場合、どのようにすればよいのでしょうか? 効率よく設定したいのですが・・・。 // bit // 23 - 21:week1 // 20 - 18:week2 // 17 - 15:week3 // 14 - 12:week4 // 11 - 9:week5 // 8 - 6:week6 // 5 - 3:week7 // 2 - 0:week8 unsigned char week[3]; 上記の変数にこの変数の内容を設定する // 以下の変数の範囲は 0~7 unsigned char week1; unsigned char week2; unsigned char week3; unsigned char week4; unsigned char week5; unsigned char week6; unsigned char week7; unsigned char week8; ---------------- week[0] = ( week1 << 5 ) & ( week2 << 2 ) & ( week3 >> 1 )  ・ ・ ・ 上記のような感じで設定できると思うのですが、もっと効率的に方法はないでしょうか? 配列の数が多くなると面倒ですので。。。 よろしくお願いします。

専門家に質問してみよう