---
# System prepended metadata

title: bitwise 操作
tags: [C 語言筆記]

---

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