--- title: bitwise 操作 tags: C 語言筆記 --- ## bitwise 操作 ### 位移運算子(Shift operator): * 邏輯位移 (Logical shift) : 左側會補上 0 * 算術位移 (Arithmetic shift) : 補上號數 (sign bit) 也就是最高有效位元的值在左側 * gcc 的實作上是使用 arithmetic shift * signed、unsigned 做運算,系統會優先都轉成 unsigned * 意外結果的案例: 判斷式 ``` i - sizeof(char) ```,因為是 signed number - unsigned number,所以系統會自動把 i 轉成 unsigned 後再進行減法導致判斷式永遠都是 true ```c= int n = 10; for (int i = n - 1 ; i - sizeof(char) >= 0; i--) printf("i: 0x%x\n",i); ``` * Bitwise Manipulation: * ```1 << x```: 2 to the power x * ```~x + 1```: -x, arithmetic negation * ```x >> 31```: -1 if x is negative, 0 otherwise * ```x &= (x - 1)```: clears lowest "on" bit in x * ```(x ^ y) < 0```: true if x and y have opposite signs * Set a bit: 將第 n 個 bit 設成 1 ```c= unsigned char a |= (1 << n); ex: a 1 0 0 0 0 0 0 0 a |= (1 << 1) = 1 0 0 0 0 0 1 0 a |= (1 << 3) = 1 0 0 0 1 0 0 0 a |= (1 << 5) = 1 0 1 0 0 0 0 0 ``` * Clear a bit:: 將第 n 個 bit 設成 0 ```c= unsigned char b &= ~(1 << n); ex: b 1 1 1 1 1 1 1 1 b &= ~(1 << 1) = 1 1 1 1 1 1 0 1 b &= ~(1 << 3) = 1 1 1 1 0 1 1 1 b &= ~(1 << 5) = 1 1 0 1 1 1 1 1 ``` * Toggle a bit: 將第 n 個 bit 0 、 1 互換 ```c= unsigned char c ^= (1 << n); ex: c 1 0 0 1 1 0 1 1 c ^= (1 << 1) = 1 0 0 1 1 0 0 1 c ^= (1 << 3) = 1 0 0 1 0 0 1 1 c ^= (1 << 5) = 1 0 1 1 1 0 1 1 ``` * The right/left most byte: 取左半或右半的數值 ```c= /* 以 16 bits 為例 */ unsigned char right = val & 0xff; /* 右半 */ unsigned char left = (val >> 8) & 0xff; /* 左半 */ ``` * sign bit: 判斷正負號 ```c= /* 以 16 bits 為例 */ bool sign = val & 0x8000; // sign bit ``` * 印出 binary ```c= /* 版本一 */ void binary(unsigned int n) { for (int i = 256; i > 0; i /= 2) { if (n & i) printf(" 1"); else printf(" 0"); } printf("\n"); } /* 版本二 */ bool getBit(int n, int index) { return ((n & (1 << index)) > 0); } for (int i = 7; i >= 0; i--) printf("%d ", getBit(num,i)); ``` ### bitwise 練習題 * [2018q1](https://hackmd.io/@willwillhi/BJS5-SGn9) * [2018q3](https://hackmd.io/@willwillhi/r1D75_zn5) * [2019q1 第一周](https://hackmd.io/@willwillhi/SkZD_eE25) * [2019q1 第二周](https://hackmd.io/@willwillhi/ByWw5xrnq) * [2020q1](https://hackmd.io/@willwillhi/BkiAtDInc) * [2020q3](https://hackmd.io/@willwillhi/HJUfrkFh9)