# 2018q3 Homework5 (bits)
contributed by < [`letticee`](https://github.com/letticee) >
## 環境設定
* 問題
```
$ sudo apt install libc6-dev:i386 gcc:i386
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
有些套件無法安裝。這可能意謂著您的要求難以解決,或是若您使用的是
unstable 發行版,可能有些必要的套件尚未建立,或是被移出 Incoming 了。
以下的資訊或許有助於解決當前的情況:
下列的套件有未滿足的相依關係:
gcc:i386 : 相依關係: cpp:i386 (>= 4:7.3.0-3ubuntu2.1) 但它卻將不會被安裝
相依關係: gcc-7:i386 (>= 7.3.0-27~) 但它卻將不會被安裝
E: 無法修正問題,您保留 (hold) 了損毀的套件。
```
* 解決方式
* 依指示安裝有相依的套件後,make 時會產生 error
```
$ make
gcc -O0 -g -Wall -Werror -m32 -lm -o btest bits.c btest.c decl.c tests.c
/usr/lib/gcc/i686-linux-gnu/7/../../../../i686-linux-gnu/bin/ld: /usr/lib/gcc/i686-linux-gnu/7/liblto_plugin.so: 載入外掛程式時發生錯誤: /usr/lib/gcc/i686-linux-gnu/7/liblto_plugin.so: 錯誤 ELF 類別:ELFCLASS32
collect2: error: ld returned 1 exit status
Makefile:13: recipe for target 'btest' failed
make: * [btest] Error 1
```
* 安裝 gcc-multilib 可以解決
```
$ sudo apt install gcc-multilib
```
## bits.c
### absVal
* 想法
* ~~考試題目有出現~~
* `x` 為正的話, `x ^ y` 等於 `x`,`~y + 1` ; `x` 為負的話, `x ^ y` 等於 `~x` ,`~y + 1` 為 1,`(x ^ y) + (~y + 1)` 就是 `x` 的二補數
```C
int absVal(int x)
{
int y = x >> 31;
return (x ^ y) + (~y + 1);
}
```
* commit 時會產生 error
```
$ git commit
[bits.c:114]: (error) Shifting signed 32-bit value by 31 bits is undefined behaviour
```
:::warning
為什麼是 undefined behaviour
:::
* 將 `x >> 31` 改成 `x >> 30 >> 1` 就不會產生 error
```C
int absVal(int x)
{
int y = x >> 30 >> 1;
return (x ^ y) + (~y + 1);
}
```
### addOK
* 想法
* 發生 overflow 的情況
* 正數相加結果為負數
* 負數相加結果為正數
* 判斷 `x + y` 的 sign bit 是否和 `x`、`y` 的相同,若都不同,則為發生 overflow
* `x + y` 的 sign bit 是否和 `x` 的相同 (不同會是 1):
* `x ^ sum >> 31`
* `x + y` 的 sign bit 是否和 `y` 的相同 (不同會是 1):
* `y ^ sum >> 31`
* 若上面兩個結果都是 1,則發生 overflow
```C
int addOK(int x, int y)
{
int sum = x + y;
return !(((x ^ sum) & (y ^ sum)) >> 30 >> 1);
}
```
### allEvenBits
* 想法
*