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

msc*_*msc 131 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;
}
Run Code Online (Sandbox Code Playgroud)

输出(GCC):

1
1
4 // Why 4?
Run Code Online (Sandbox Code Playgroud)

但在这里,

printf("%zu\n", sizeof(a ? true : false)); // Why 4?
Run Code Online (Sandbox Code Playgroud)

三元运算符返回boolean类型,sizeof bool类型是1C中的字节.

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

Jus*_*tin 223

这是因为你有#include <stdbool.h>.该标头定义宏 true并且false10,所以你的语句如下所示:

printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?
Run Code Online (Sandbox Code Playgroud)

sizeof(int) 在您的平台上是4.

  • "这是因为你有#include <stdbool.h>"不,它不是.`sizeof(a?(uint8_t)1:(uint8_t)0);`也会得到4的结果.`?``操作数的整数提升是这里的重要部分,而不是`true`和`的大小.返回FALSE. (19认同)
  • @Lundin:两者都很重要.如上所述,该类型已经是`int`而没有促销.您无法"修复"它的原因是默认促销. (8认同)
  • @PeterSchneider这不是C++.这是C.在C++中,`true`和`false`是*不是*宏; 他们是关键词.它们没有定义为`1`和`0`,而是`bool`类型的真值和假值. (5认同)
  • @PeterSchneider不,你今天学到了一些关于C的东西.不要混淆这两种语言.在C++中,`sizeof(true)`是1. [demo](https://godbolt.org/g/UG6tEq). (4认同)

Sou*_*osh 66

这里,三元运算符返回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)是真正符合标准的.


n. *_* m. 57

三元运算符是红鲱鱼.

    printf("%zu\n", sizeof(true));
Run Code Online (Sandbox Code Playgroud)

打印4(或sizeof(int)平台上的任何内容).

以下假定它boolchar大小为1 的同义词或类似类型,并且int大于char.

之所以sizeof(true) != sizeof(bool)sizeof(true) == sizeof(int)仅仅是因为true不是类型的表达bool.这是一种类型的表达int.它#define就像1stdbool.h.

boolC 中根本没有rvalues类型.int即使用作参数,每个这样的rvalue也会被立即提升sizeof.编辑:这段不是真的,参数sizeof不要升级到int.但这并不影响任何结论.

  • 我认为答案以最佳方式解决了这个问题.欢迎您进行投票或改进. (6认同)
  • 不是`(bool)1`是`bool`类型的左值? (5认同)

Lun*_*din 30

关于C中的布尔类型

在1999年,在C语言中引入了布尔类型.在此之前,C没有布尔类型,而是用于int所有布尔表达式.因此,诸如> == !等的所有逻辑运算符都返回int10.

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

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

stdbool.h提供与C++的一些兼容性.此标头定义了bool扩展为的宏(与C++关键字相同的拼写),_Bool这是一种小整数类型,可能是1字节大.类似地,头提供两个宏truefalse,相同拼写C++的关键字,但与较旧的C程序的后向兼容性.因此truefalse扩展到10C和它们的类型是int.这些宏实际上不是像相应的C++关键字那样的布尔类型.

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

关于条件运算符 ?:

条件运算符?:是一个奇怪的运算符,有几个怪癖.认为它与100%相当是一个常见的错误if() { } else {}.不完全的.

在第1和第2或第3操作数的评估之间存在序列点.该?:操作员是保证仅评估任一第二或第三操作数,所以它不能执行该不评估操作数的任何副作用.代码就像true? func1() : func2()不会执行func2().到现在为止还挺好.

但是,有一个特殊规则表明第二个和第三个操作数必须通过通常的算术转换进行隐式类型提升和相互平衡.(C中的隐式类型促销规则在此解释).这意味着第二个或第三个操作数将始终至少与a一样大int.

所以不要紧,true并且false恰好是类型的int在C,因为表达总是给的至少大小int没有关系.

即使你将表达式重写为 它仍然会返回一个大小!sizeof(a ? (bool)true : (bool)false) int

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


chq*_*lie 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类型,布尔值true以及false比较运算符和三元运算符的不同语义:所有这些sizeof()表达式都1在C++中求值.

  • 好的答案实际上指出了什么类型`true`和`false`并不重要,因为`?:`操作数无论如何都会将整数提升为`int`.因此`sizeof(a?(uint8_t)true:(uint8_t)false)`也会产生4. (2认同)