为什么" sizeof(a?true:false)"给出四个字节的输出?

时间:2017-10-30 08:37:05

标签: c boolean sizeof conditional-operator c11

我有一小段关于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?

三元运算符返回boolean类型,而bool类型的大小为1字节。

然后为什么sizeof(a ? true : false)给出四个字节的输出?

7 个答案:

答案 0 :(得分:224)

这是因为你有#include <stdbool.h>。该标头defines macros truefalse10,因此您的声明如下:

printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?

sizeof(int)在您的平台上为4。

答案 1 :(得分:67)

  

此处,三元运算符返回boolean类型,

好的,还有更多内容!

在C中, 三元操作的结果属于int类型。 [注释(1,2)]

因此,结果与您平台上的表达式sizeof(int)相同。

注1:引用C11,章节§7.18,Boolean type and values <stdbool.h>

  

[....]其余三个宏适用于#if预处理指令。他们   是

     

true

     

扩展为整数常量1,

     

false

     

扩展为整数常量0,[....]

注2:对于条件运算符,章节§6.5.15,(强调我的

  

评估第一个操作数;它的评价和评价之间有一个序列点   评估第二或第三操作数(以评估者为准)。第二个操作数   仅当第一个比较不等于0时才计算;第三个操作数仅在以下情况下进行评估   第一个比较等于0; 结果是第二个或第三个操作数的值   (无论哪个评估), [...]

  

如果第二个和第三个操作数都有算术类型,那么结果类型就是   通过通常的算术转换确定它们是否应用于这两个操作数,   是结果的类型。 [....]

因此,结果将是整数类型,并且由于值范围,常量恰好是类型int

尽管如此,通用建议int main()最好int main (void)才能真正符合标准。

答案 2 :(得分:58)

三元运算符是红鲱鱼。

    printf("%zu\n", sizeof(true));

打印4(或平台上的sizeof(int))。

以下假设boolchar的同义词或相似类型的大小1,int大于char

sizeof(true) != sizeof(bool)sizeof(true) == sizeof(int)的原因仅仅是因为true 不是类型为bool的表达式。它是int类型的表达式。 #define中的1stdbool.h

C中根本没有bool类型的右值。每个这样的rvalue都会立即提升为int,即使用作sizeof的参数。编辑:此段落不正确,sizeof的参数不会被提升到int。但这并不影响任何结论。

答案 3 :(得分:30)

关于C

中的布尔类型

在1999年的C语言中引入了布尔类型。在此之前,C没有布尔类型,而是使用int表示所有布尔表达式。因此,> == !等所有逻辑运算符都返回值为int1的{​​{1}}。

自定义应用程序使用自制类型,例如0,它也可以归结为typedef enum { FALSE, TRUE } BOOL;大小的类型。

C ++有一个更好的显式布尔类型int,它不大于1个字节。而在最坏的情况下,C中的布尔类型或表达式最终会变为4个字节。使用C99标准在C中引入了与C ++的某种兼容方式。然后,C得到一个布尔类型bool以及标题_Bool

stdbool.h提供了与C ++的一些兼容性。此标头定义宏stdbool.h(与C ++关键字相同的拼写),扩展为bool,这是一种小整数类型,可能是1字节大。同样,标头提供了两个宏_Booltrue,拼写与C ++关键字相同,但与旧C程序具有向后兼容性。因此,falsetrue扩展为C中的false1,其类型为0。这些宏实际上不是布尔类型,就像相应的C ++关键字一样。

同样,为了向后兼容,C 中的逻辑运算符仍然返回int到今天,即使C现在有一个布尔类型。在C ++中,逻辑运算符返回int。因此,诸如bool之类的表达式将在C中给出sizeof(a == b)的大小,但在C ++中给出int的大小。

关于条件运算符bool

条件运算符?:是一个奇怪的运算符,有几个怪癖。认为它与?: 100%相等是一个常见的错误。不太好。

在第1和第2或第3操作数的评估之间存在序列点。保证if() { } else {}运算符仅评估第2或第3个操作数,因此它不能执行未评估的操作数的任何副作用。像?:这样的代码不会执行true? func1() : func2()。到目前为止,非常好。

然而,有一个特殊的规则,规定第二个和第三个操作数必须通过通常的算术转换进行隐式类型提升和相互平衡。 (Implicit type promotion rules in C explained here)。这意味着第二个或第三个操作数总是至少与func2()一样大。

因此,inttrue碰巧在C中的false类型并不重要,因为表达式总是至少提供int的大小不管。

即使您将表达式重写为 int ,它仍会返回 sizeof(a ? (bool)true : (bool)false)

这是因为通过通常的算术转换进行隐式类型提升。

答案 4 :(得分:21)

快速回答:

  • sizeof(a ? true : false)评估为4,因为truefalse分别在<stdbool.h>中定义为10,因此表达式扩展为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

  • 还请注意,比较运算符会评估为布尔值10,但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类型,布尔值truefalse,比较运算符和三元运算符的不同语义:所有这些sizeof()表达式在C ++中评估为1

答案 5 :(得分:1)

以下是源代码中包含的内容

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

truefalse分别声明为1和0。

但是在这种情况下,type是文字常量的类型。 0和1都是适合int的整数常量,因此它们的类型是int。

,您案例中的sizeof(int)为4。

答案 6 :(得分:-2)

C中没有布尔数据类型,而当1为真时,逻辑表达式计算为整数值0

ifforwhilec ? a : b等条件表达式需要一个整数,如果该数字不为零则认为true除外一些特殊情况,这里是一个递归求和函数,其中三元运算符将评估true直到n到达0

int sum (int n) { return n ? n+sum(n-1) : n ;

它也可用于NULL检查指针,这是一个打印单链接列表内容的递归函数。

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }