いつもいつも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 のテストです。
# 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 目を出力しています。
# 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 をかけてシフトしていますが、もっと頭の良い方法もあったと思います。
まとめ
今回はとりあえずメモでした。いつも確認コードを書かないと分からなくなってしまうのですが、今回も、目的の実装はできてのりきれました。ふー。
今後、なにか思い出したりしたら追記したいと思います。