{%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 ```