我有一小段关于带有三元运算符的 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;
}
Output (GCC):
1
1
4 // Why 4?
但在这里,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
三元运算符返回 boolean
类型,sizeof bool
类型在C中为 1
字节 .
然后 why does sizeof(a ? true : false) give an output of four bytes?
7 回答
这是因为你有
#include <stdbool.h>
. Headers defines macrostrue
和false
是1
和0
,所以你的语句如下所示:sizeof(int)
在您的平台上是4 .好的,还有更多!
在C中, this 三元运算的结果是
int
类型 . [下面的注释(1,2)]因此,结果与您平台上的表达式
sizeof(int)
相同 .注1:引用
C11
,章节§7.18,Boolean type and values <stdbool.h>
注2:对于条件运算符,章节§6.5.15,(强调我的)
和
因此,结果将是整数类型,并且由于值范围,常量的类型为
int
.也就是说,一个通用的建议,最好是
int main (void)
才能真正符合标准 .三元运算符是红鲱鱼 .
打印4(或任何
sizeof(int)
在您的平台上) .以下假设
bool
是char
的同义词或类似类型的大小1,int
大于char
.sizeof(true) != sizeof(bool)
和sizeof(true) == sizeof(int)
之所以仅仅因为true
是 not 是bool
类型的表达式 . 它是int
类型的表达式 . 在stdbool.h
中#define
为1
.C中根本没有rol类型的rvalues . 即使用作sizeof的参数,每个这样的rvalue也会立即提升为int . 编辑:此段落不正确,
sizeof
的参数不会升级为int
. 但这并不影响任何结论 .Regarding the boolean type in C
在1999年,在C语言中引入了布尔类型 . 在此之前,C没有布尔类型,而是使用
int
用于所有布尔表达式 . 因此,所有逻辑运算符(如> == !
等)都返回值1
或0
的int
.应用程序可以自定义使用自制类型,例如
typedef enum { FALSE, TRUE } BOOL;
,它也归结为int
-sized类型 .C有一个更好的显式布尔类型
bool
,它不大于1个字节 . 虽然在最坏的情况下,C中的布尔类型或表达式最终会变为4个字节 . 使用C99标准在C中引入了与C的某种兼容方式 . C然后得到一个布尔类型_Bool
和 Headersstdbool.h
.stdbool.h
提供了与C的一些兼容性 . 此标头定义宏bool
(与C关键字相同的拼写),扩展为_Bool
,这是一种小整数类型,可能是1字节大 . 同样, Headers 提供了两个宏true
和false
,与C关键字的拼写相同,但与旧C程序具有向后兼容性 . 因此true
和false
在C中扩展为1
和0
,其类型为int
. 这些宏实际上不是像对应的C关键字那样的布尔类型 .类似地,为了向后兼容的目的,C中的逻辑运算符仍然返回
int
到今天,即使C现在有一个布尔类型 . 在C中,逻辑运算符返回bool
. 因此,诸如sizeof(a == b)
之类的表达式将在C中给出int
的大小,但在C中给出bool
的大小 .Regarding the conditional operator ?:
条件运算符
?:
是一个奇怪的运算符,有几个怪癖 . 认为它与if() { } else {}
完全相同是一个常见的错误 . 不完全的 .在第1和第2或第3操作数的评估之间存在序列点 . 保证
?:
运算符仅评估第2或第3个操作数,因此它不能执行未计算的操作数的任何副作用 . 像true? func1() : func2()
这样的代码不会执行func2()
. 到现在为止还挺好 .但是,有一个特殊的规则,规定第二个和第三个操作数必须隐式类型提升并对每个操作数进行 balancer 其他与通常的算术转换 . (Implicit type promotion rules in C explained here) . 这意味着第二个或第三个操作数将始终至少与
int
一样大 .因此,
true
和false
恰好在C中的类型为int
并不重要,因为表达式总是至少给出int
的大小 .Even if you would rewrite the expression to sizeof(a ? (bool)true : (bool)false) it would still return the size of an int !
这是因为通过通常的算术转换进行隐式类型提升 .
快速回答:
sizeof(a ? true : false)
求值为4
,因为true
和false
分别在<stdbool.h>
中定义为1
和0
,因此表达式扩展为sizeof(a ? 1 : 0)
,这是一个类型为int
的整数表达式,占用平台上的4个字节 . 出于同样的原因,sizeof(true)
也会在您的系统上评估为4
.但请注意:
sizeof(a ? a : a)
也计算为4
,因为三元运算符在其第二个和第三个操作数上执行整数提升,如果它们是整数表达式 . 对于sizeof(a ? true : false)
和sizeof(a ? (bool)true : (bool)false)
当然也是如此,但是将整个表达式转换为bool
的行为符合预期:sizeof((bool)(a ? true : false)) -> 1
.还注意比较运算符求值为布尔值
1
或0
,但int
类型:sizeof(a == a) -> 4
.保持
a
的布尔性质的唯一运算符将是:逗号运算符:编译时
sizeof(a, a)
和sizeof(true, a)
计算为1
.赋值运算符:
sizeof(a = a)
和sizeof(a = true)
的值均为1
.增量运算符:
sizeof(a++) -> 1
最后,以上所有内容仅适用于C:C具有与
bool
类型,布尔值true
和false
,比较运算符和三元运算符不同的语义:所有这些sizeof()
表达式在C中计算为1
.以下是源代码中包含的内容片段
宏
true
和false
分别声明为1和0 .但是在这种情况下,类型是文字常量的类型 . 0和1都是适合int的整数常量,因此它们的类型是int .
在你的情况下
sizeof(int)
是4 .C中没有布尔数据类型,而是逻辑表达式计算为整数值
1
,否则为0
.像
if
,for
,while
或c ? a : b
这样的条件表达式期望一个整数,如果该数字非零,则除了一些特殊情况外,它被认为是true
,这里是一个递归求和函数,其中三元运算符将评估true
,直到n
到达0
.它也可用于检查指针,这是一个打印单链接列表内容的递归函数 .