[英]Why doesn't comparison with bool convert to bool in C11?
給出以下C11代碼:
int a = 1234;
bool b = (bool)a; // equivalent to (a != 0) or (a != false) which evaluates to 1 or true
if (a) // equivalent to if(a != 0) or if (a != false) which evaluates to 1 or true
printf("a\n");
if (a == (bool)true) // should be equivalent to if(!(a == false)) or if (a != false)
printf("a == (bool)true\n");
我知道true是#define true 1
但bool
顯然不是普通的整數類型,因為(bool)0.1
值計算為1,而強制轉換為int的結果將為0。
1)為什么沒有true
定義為(bool)1
? 這將允許編譯器至少輸出警告。
2)為什么我的示例中的整數沒有轉換為bool
,以致a == (bool)true
會評估為(bool)a == (bool)true
,這實際上是正確的?
為什么在C11中不能將與bool進行比較轉換為bool?
_Bool
是最低的級別,等於運算符==
指定其_Bool
操作數提升為int
。 @說故事的人
_Bool
的等級應小於所有其他標准整數類型的等級。 C11§6.3.1.11(相等運算符)如果兩個操作數都具有算術類型,則執行常規的算術轉換。 §6.5.94
(通常是算術轉換)...對兩個操作數§6.3.1.81都執行整數提升。
(整數提升)如果一個
int
可以表示原始類型的所有值...該值將轉換為一個int
...§6.3.1.12
OP的代碼示例沒有與bool的比較。
// int compared to int: false since a == 1234 and that is not equal 1
if (a == true)
相反,本來可以
// int compared to _Bool: false since a == 1234 and that is not equal to 0 or 1
if (a == b)
使用int == _Bool
, int == short
, int == signed char
,會發生相同的情況。 較低級別的操作數被提升為int
。
1)為什么沒有真正定義為(bool)1? 這將允許編譯器至少輸出警告。
為什么? 幾年前的標准委員會決定。 當引入_Bool
,將true
視為(int)1
而不是(_Bool)1
肯定會對現有代碼產生較小的影響。 (C99)。 這與其他子int
常量(例如SHRT_MAX
)一致,后者通常是int
,而不是short
。 在任何情況下,在大多數情況下,在進行進一步處理之前int/unsigned
,就像在這種比較情況下一樣。
不再需要(_Bool)1
來允許編譯器提供警告。 可以使用各種分析工具制作提供警告的編譯器。 與(_Bool)1
,它可以簡化編譯器提供此類警告的過程。
2)為什么在我的示例中,該整數未轉換為
bool
,使得a == true
會評估為(bool)a == true
,而實際上是true?
作為true
是一個(int)1
,具有a == true
,兩個操作數都int
。 _Bool
在這里不適用。
2)[OP更新]為什么我的示例中的整數沒有轉換為
bool
,使得a == true
會評估為(bool)a == true
,而實際上會是true?
答案的最上面是這樣的: int
中為true
,因此(bool)a
在比較之前被提升為int
,因為int
的等級高於_Bool
。
我知道true是
#define true 1
但bool
顯然不是普通的整數類型,因為(bool)0.1
值計算為1,而強制轉換為int的結果將為0。
bool
(實際上是_Bool
; bool
是擴展為_Bool
的宏)是整數類型。 它確實具有一個不尋常的功能,它不與任何其他類型共享:將任何非零值轉換為_Bool
產生1
。
請注意,產生邏輯布爾值的運算符仍會產生值為0
或1
的int
結果。 由於隱式轉換,這通常不是問題。
1)為什么沒有
true
定義為(bool)1
? 這將允許編譯器至少輸出警告。
允許編譯器在需要時發出警告。 在比較警告true
或false
將是一個不錯的主意。
2)為什么在我的示例中,該整數未轉換為
bool
,使得a == true
會評估為(bool)a == true
,而實際上是true?
a == true
必須先將其操作數轉換為相同類型,然后才能進行比較。 這是通過通常的算術轉換完成的 。 規則(相當復雜)在N1570的 6.3.1.8節中進行了描述。 一個非常快速和不精確的總結是,較窄類型(較小整數轉換等級 )的操作數將轉換為另一個操作數的類型。 例如,當您比較int
和long
類型的表達式時, int
操作數將提升為long
。 _Bool
最窄整數類型,所以它總是在比較促進除非它被另一個相比_Bool
值。
僅為_Bool
更改這些規則會造成混亂,並且確實不會給您帶來多少好處。
底線:請勿將相等值與false
或true
進行比較。 不要寫:
if (a == true)
寫吧:
if (a)
如果那是你的意思。 同樣,不要寫:
if (a == false)
寫吧
if (!a)
從評論中總結:
_Bool
實際上是“僅”另一種無符號整數類型,其例外規則是,如果值不等於0(“ false”),則轉換為結果始終為1(“ true”)。
因為它是一個無符號整數,所以適用積分促銷規則。 即使將true
定義為(bool)1
,比較a == true
也會導致實際比較1234 == 1
,這始終是false
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.