{%hackmd BJrTq20hE %}
# 你用的 bool 不是真正的 _Bool
> 與 Embedded Software Engineer 相關的問題,歡迎透過 Linkedin 與我聯繫
[**Linkedin**](https://www.linkedin.com/in/chao-shun/)
## 一開始認識的 bool
從大學的計算機概論,就知道有 `bool` 這個資料型態,並且老師總是教只要有記得 `include` 正確的 Header File 就可以使用,如下面的範例還可以知道,其中 `true = 1` `false = 0`
```cpp
#include <stdbool.h>
using namespace std;
int main()
{
bool b1 = true;
bool b2 = false;
cout << b1 <<" , "<< b2;
return 0;
}
```
```bash
> 1 , 0
```
另外 `bool` 也可以跟 `if` 搭配著使用,如下面的範例,就是一種很常見的 `bool` 使用方式
```cpp
#include <stdbool.h>
using namespace std;
bool isEqual(int x, int y)
{
return (x == y);
}
int main()
{
int x = 10;
int y = 20;
int z = 10;
if (isEqual(x, y))
cout << "x is equal to y\n";
else
cout << "x is not equal to y\n";
if (isEqual(x, z))
cout << "x is equal to z\n";
else
cout << "x is not equal to z\n";
return 0;
}
```
```bash
> x is not equal to y
> x is equal to z
```
因此在我踩到坑之前,我所認知的 `bool` 是
* 只有 `1` and `0`
* `bool` 就像是 `int` 一樣,是一種 Data Type
## 我認識的 bool 竟然不是 _Bool
有次基於現有的 Driver Code 上面要再加上支援 Suspend / Resume 的功能,因此去 `#include <linux/suspend.h>` ,沒想到在 Native Kernel 當中出現 Compile Error 的狀況
```bash
./include/linux/memcontrol.h:961:9: error: incompatible pointer to
integer conversion returning 'struct mem_cgroup *' from a function with
result type 'unsigned char' [-Wint-conversion]
```
看 Compile Error 的訊息回去看 Source Code 是下面這段,可以看到 Return Type 是 `bool` 但回傳的卻是 `Pointer`,所以認為是發生 **implicit type conversion**
```c
// the member of task_struct
struct mem_cgroup *memcg_in_oom;
// include/linux/memcontrol.h
static inline bool task_in_memcg_oom(struct task_struct *p)
{
return p->memcg_in_oom;
}
```
還提了個 Patch 到 LKML 說明應該避免使用 **implicit type conversion**
[**[PATCH] mm: avoid implicit type conversion**](https://lore.kernel.org/all/20250107035141.2858582-1-chao.shun.cheng.tw@gmail.com/)
## C99 _Bool
信發出去馬上就有高手看出問題並且回覆如下
> That makes no sense. Do you have bool (or _Bool) defined or typedefed to unsigned char somewhere? If so, that's the bug that needs to be fixed.
回頭檢視 C99 規格書對於 bool 的定義,發現真正的 Data Type 是 `_Bool` 並非 `bool`,`bool` 應是為了 User 方便開發後續才在 Header 當中去進行 `typedef`。此外規格書還提到,任何值傳進去給 `_Bool` 都會先去做比較,值假如是 0 那就會是 0 , 否則都會是 1,這也就說明 Native Code 為什麼沒問題,假設 `Pointer` 是 `NULL` 那就會回傳 0 , 反之就傳 1
***6.3.1.2 Boolean type***
> When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.
重新檢查 Native Kernel 當中對於 `bool` 的定義,確實是把 `_Bool` 透過 `typedef` 等價於 `bool`
```c
// include/linux/types.h
typedef _Bool bool;
```
回頭看我改的 Driver Code 上面還真的有個 Header 自行先去定義 `bool`,所以到這邊就可以確定是我搞烏龍,改別人的 Driver Code 之前還要先檢查他之前用的 Header or Coding 方式是否有不符合預期的地方,不然就會一直遇到類似的問題
```c
#ifndef bool
#define bool unsigned char
#endif
```