0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C】bitwise operator メモ

Last updated at Posted at 2020-12-28

いつもいつもC言語で必要になるたびに調べているのでメモを書いておきます。今回も調べました。(涙)

Bitwise Operator

書き方

どこを本家として参照すればよいのか分かりませんが、Wikipediaがあったので、リンクをメモリます。

Symbol Operator
& bitwise AND
| bitwise inclusive OR
^ bitwise XOR (exclusive OR)
<< left shift

| right shift
~ | bitwise NOT (one's complement) (unary)

出力してみる

以下、NOT operator のテストです。

test.c
# include <stdio.h>

void printBi(char num) {
  int len = 8;
  int bit[8];

  for(int i = 0; i < len; i++) {
    int x = 1 << i;
    x = num & x;
    bit[len - i - 1] = x >> i;
  }

  printf("0b");
  for(int i = 0; i < len; i++) {
    printf("%d", bit[i]);
  }
}

int main(void) {
  int num = 0b00000101;
  int result = ~num;

  printf("Input  %4d(Decimal) ", num);
  printBi(num);
  printf("(Binary)\n");
  printf("Output %4d(Decimal) ", result);
  printBi(result);
  printf("(Binary)\n");
  return 0;
}

gcc でコンパイルして実行すると、以下を得ます。

Input     5(Decimal) 0b00000101(Binary)
Output   -6(Decimal) 0b11111010(Binary)

flag を読む

実際に必要となったのは、4byte のデータの2byte 目の3bit 目のbinary を読みたい、のような場面です。

2byte, 3bit の(開始から8+3=11 bitの位置)の値を読みたいとします。次の^ の位置です。

0b00100000 00001100 00000000 00000000
                ^

いろいろデータのの取り出し方はあります。以下は、bit mask とシフトで必要なflag を読むためのテストコードです。4byte の各データの3bit 目を出力しています。

test2.c
# include <stdio.h>
# include <stdint.h>

void print_binary_byte(unsigned char num) {
    int len = 8;
    int bit[8];
    for(int i = 0; i < len; i++) {
        int x = 1 << i;
        x = num & x;
        bit[len - i - 1] = x >> i;
    }
    for(int i = 0; i < len; i++) {
        printf("%d", bit[i]);
    }
}

void print_binary_bytes(unsigned char* buf, unsigned int buflen) {
  printf("0b");
  for(unsigned int i=0; i<buflen; i++){
    print_binary_byte(buf[i]);
    printf(" ");
  }
  printf("\n");
  for(unsigned int i=0; i<buflen; i++){
    unsigned char v0 = buf[i];
    unsigned char v2 = (v0 & 0b00000100) >> 2;
    printf("[%d/%d] 0b", i, buflen);
    print_binary_byte(v0);
    printf("(input) ");
    printf(" 0b00000100(mask) --> shift --> 0b");
    print_binary_byte(v2);
    printf("(output)\n");
  }
}

int main(void) {
    uint32_t val1 = 32 + 1024 + 2048;
    union bytes4{
      unsigned char buf[4];
      uint32_t val_uint32;
    };
    union bytes4 val1_union;
    val1_union.val_uint32 = val1;
    print_binary_bytes(val1_union.buf, sizeof(val1_union.buf));
    return 0;
}

実行すると、以下を得ます。

0b00100000 00001100 00000000 00000000
[0/4] 0b00100000(input) 0b00000100(mask) --> shift --> 0b00000000(output)
[1/4] 0b00001100(input) 0b00000100(mask) --> shift --> 0b00000001(output)
[2/4] 0b00000000(input) 0b00000100(mask) --> shift --> 0b00000000(output)
[3/4] 0b00000000(input) 0b00000100(mask) --> shift --> 0b00000000(output)

1だったことが分かります。mask をかけてシフトしていますが、もっと頭の良い方法もあったと思います。

まとめ

今回はとりあえずメモでした。いつも確認コードを書かないと分からなくなってしまうのですが、今回も、目的の実装はできてのりきれました。ふー。

今後、なにか思い出したりしたら追記したいと思います。

0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?