为什么sizeof(a?true:false)给出四个字节的输出?
我有一个关于sizeof运算符与三元运算符的一小段代码: 
 #include <stdio.h> #include <stdbool.h> int main() { bool a = true; printf("%zu\n", sizeof(bool)); // Ok printf("%zu\n", sizeof(a)); // Ok printf("%zu\n", sizeof(a ? true : false)); // Why 4? return 0; } 
输出( GCC ):
 1 1 4 // Why 4? 
但在这儿,
 printf("%zu\n", sizeof(a ? true : false)); // Why 4? 
 三元运算符返回booleantypes,size的booltypes是C中的1个字节。 
 那么为什么sizeof(a ? true : false)给出了四个字节的输出? 
 这是因为你有#include <stdbool.h> 。 这个头文件定义macros的 false为1和0 ,所以你的语句如下所示: 
 printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4? 
  sizeof(int)在你的平台上是4。 
这里,三元运算符返回
booleantypes,
好的,还有更多!
 在C中, 这个三元操作的结果是inttypes的。  [下面的注释(1,2)] 
 因此,结果与您的平台上的expression式sizeof(int)相同。 
 注1:引用C11 ,章节§7.18, Boolean type and values <stdbool.h> 
[…]其余的三个macros适用于
#if预处理指令。 他们是
true其展开为整数常数1,
false扩展到整数常量0,[…]
注2:对于条件操作符,§6.5.15( 强调我的 )
第一个操作数被评估; 在其评估和第二或第三操作数的评估之间有一个顺序点(以评估者为准)。 第二个操作数仅在第一个操作数比较不等于0时才被计算; 第三个操作数仅在第一个操作数比较等于0时才被评估; 结果是第二个或第三个操作数的值(以评估者为准), […]
和
如果第二个和第三个操作数都具有算术types,那么将由通常的算术转换确定的结果types应用于这两个操作数,结果的types。 [….]
 因此,结果将是整型,由于值的范围,这些常量正好是inttypes的。 
 也就是说,一个通用的build议, int main()最好是int main (void) ,真正符合标准。 
三元运算符是一个红色的鲱鱼。
  printf("%zu\n", sizeof(true)); 
 打印4(或任何sizeof(int)在您的平台上)。 
 下面假定bool是char或者大小为1的类似types的同义词,并且int大于char 。 
  sizeof(true) != sizeof(bool)和sizeof(true) == sizeof(int)很简单,因为true 不是一个booltypes的expression式。 这是一个inttypes的expression式。 在stdbool.h中将#define d设置为1 。 
  C中根本不存在types  bool右bool 。即使用作 编辑:这个段落不是真的, sizeof的参数,每个这样的右值立即被提升为int 。sizeof参数不会被提升为int 。 尽pipe如此,这并不影响任何结论。 
关于C中的布尔types
 在1999年,一种布尔types在C语言中引入相当晚。在此之前,C没有布尔types,而是对所有布尔expression式使用int 。 因此所有逻辑运算符如> == ! 等返回一个值为1或0的int 。 
 这是自定义的应用程序使用自制的types,如typedef enum { FALSE, TRUE } BOOL;  ,这也归结为int sizedtypes。 
  C ++有一个更好的,明确的布尔types, bool ,不大于1个字节。 尽pipeC中的布尔types或expression式在最坏的情况下最终会变成4字节。 用C ++标准在C语言中引入了一些与C ++兼容的方法。  C然后得到一个布尔types_Bool和头stdbool.h 。 
  stdbool.h提供了一些与C ++的兼容性。 这个头文件定义了macrosbool (与C ++关键字相同的拼写),扩展为_Bool ,这是一个小整数types,可能是1个字节。 同样,头文件提供了两个macros,分别是true和false ,与C ++关键字相同, 但与旧的C程序兼容 。 因此,C和C中的true和false展开为1和0 ,它们的types是int 。 这些macros实际上不是像对应的C ++关键字那样的布尔types。 
 同样,为了向后兼容的目的,C中的逻辑运算符仍然返回一个int到今天,即使现今的C有一个布尔types。 在C ++中,逻辑运算符返回一个bool 。 因此,诸如sizeof(a == b)类的expression式将在C中给出int的大小,而在C ++中给出bool的大小。 
  关于条件操作符?: 
 条件运算符?:是一个奇怪的运算符,有一些怪癖。 这是一个常见的错误,相信它是100%相当于if() { } else {} 。 不完全的。 
 在第一个和第二个或第三个操作数的评估之间有一个顺序点。  ?:操作符保证只评估第二个或第三个操作数,所以它不能执行未被评估的操作数的任何副作用。 代码如true? func1() : func2()  true? func1() : func2()不会执行func2() 。 到现在为止还挺好。 
  但是 ,有一个特殊的规则,说明第二个和第三个操作数必须通过常规的算术转换相互进行隐式types提升和平衡。  ( 在这里解释隐含types的促销规则 )。 这意味着第二个或第三个操作数总是至less和int一样大。 
 所以, true和false发生在C语言中并不重要,因为expression式总是至less给出一个int的大小。 
  即使你将expression式重写为 sizeof(a ? (bool)true : (bool)false) 它仍然会返回 int 的大小 ! 
这是因为通过通常的算术转换隐式types提升。
快速回答:
-   sizeof(a ? true : false)计算结果为4因为true和false在<stdbool.h>分别定义为1和0,所以expression式展开为sizeof(a ? 1 : 0),它是一个inttypes的整数expression式,在您的平台上占用4个字节。 出于同样的原因,sizeof(true)也会在您的系统上评估为4。
但请注意:
- 
sizeof(a ? a : a)也会计算为4因为三元运算符对其第二个和第三个操作数执行整数提升(如果这些操作数是整数expression式)。sizeof(a ? true : false)和sizeof(a ? (bool)true : (bool)false)当然会发生同样的情况,但将整个expression式转换为bool行为与预期相同:sizeof((bool)(a ? true : false)) -> 1。
- 
还要注意比较运算符计算为布尔值 1或0,但是具有inttypes:sizeof(a == a) -> 4。
唯一保持a的布尔性质的运算符是:
- 
逗号运算符: sizeof(a, a)和sizeof(true, a)在编译时计算为1。
- 
赋值运算符: sizeof(a = a)和sizeof(a = true)的值均为1。
- 
增量运算符: sizeof(a++) -> 1
 最后,以上所有内容仅适用于C语言:C ++在booltypes,布尔值true和false ,比较运算符和三元运算符方面具有不同的语义:所有这些sizeof()expression式在C ++中计算为1 。 
这里是包含在源代码中的一个片段
 #ifndef __cplusplus #define bool _Bool #define true 1 #define false 0 #else /* __cplusplus */ 
 macros和false分别声明为1和0。 
然而在这种情况下,types是文字常量的types。 0和1都是整型常量,适合int,所以它们的types是int。
 在你的情况下sizeof(int)是4。 
 在C中没有布尔数据types,而是逻辑expression式计算为整数值1 ,否则为0 。 
 像if , for , while或c ? a : b这样的条件expression式c ? a : b  c ? a : b期望一个整数,如果数字非零,除了一些特殊的情况外,它被认为是true ,这里是一个recursion和函数,其中三元运算符将评估true直到n达到0 。 
 int sum (int n) { return n ? n+sum(n-1) : n ; 
 它也可以用来检查NULL指针,这里是一个recursion函数,用来打印单链表的内容。 
 void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }