为什么“ 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;
}

输出(海湾合作委员会) :

1
1
4 // Why 4?

但在这里,

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

三元运算符返回 boolean类型,bool类型的大小是 C 中的 1字节。

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

13609 次浏览

这里,三元操作符返回 boolean类型,

好吧,还有呢!

在 c 组,三元运算的结果为 int.[注(1,2)]

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


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

[ ... . ]其余三个宏适合在 #if预处理指令中使用 是

true

它展开为整数常数1,

false

它展开为整数常量0,[ ... . ]

注二: 有关条件运算符,请参阅第6.5.15章(强调我的)

对第一个操作数求值; 在其求值和 计算第二个或第三个操作数(以计算值为准) 仅当第一个操作数比较不等于0时,才计算第三个操作数; 仅当 第一个比较等于0; < strong > 结果是第二个或第三个操作数的值 (以已评估者为准) , [ ... ]

还有

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

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

也就是说,一般的建议是,int main()最好是 int main (void)才能真正符合标准。

因为你有 #include <stdbool.h>。这个头 定义宏truefalse10,所以你的陈述看起来像这样:

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

sizeof(int)在你的平台上是4。

三元操作符是一种转移注意力的方法。

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

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

下面假设 boolchar的同义词或大小为1的类似类型,并且 int大于 char

sizeof(true) != sizeof(bool)sizeof(true) == sizeof(int)的原因很简单,因为 true没有bool类型的表达。这是 int型的一种表达。在 stdbool.h中,它是 #defined,作为 1

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

快速回答:

  • sizeof(a ? true : false)的计算结果为 4,因为 <stdbool.h>中将 truefalse分别定义为 10,所以表达式展开为 sizeof(a ? 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

  • 还要注意,比较运算符的计算结果为布尔值 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

关于 C 中的布尔类型

在1999年,布尔类型在 C 语言中引入得相当晚。在此之前,C 没有布尔类型,而是对所有布尔表达式使用 int。因此,所有逻辑运算符(如 > == !等)返回值为 10int

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

C + + 有一个更好的、显式的布尔类型 bool,它不大于1字节。而 C 语言中的布尔类型或表达式在最坏的情况下会以4个字节结束。在 C 语言中引入了一些与 C + + 兼容的方式,这些方式符合 C99标准。然后得到一个布尔类型的 _Bool和头 stdbool.h

stdbool.h提供了与 C + + 的一些兼容性。这个头定义了扩展到 _Bool的宏 bool(与 C + + 关键字的拼写相同) ,_Bool是一个小整数类型,可能大于1字节。类似地,头部提供了两个宏 truefalse,拼写与 C + + 关键字 bool0相同。因此,truefalse在 C 中扩展为 10,它们的类型是 int。这些宏实际上并不像对应的 C + + 关键字那样是布尔类型的。

类似地,出于向下兼容目的,即使现在 C 语言得到的是布尔类型,但是 C 还是中的逻辑运算符仍然返回一个 int。在 C + + 中,逻辑运算符返回一个 bool。因此,像 sizeof(a == b)这样的表达式将给出 C 中 int的大小,而 C + + 中 bool的大小。

关于条件运算符

条件运算符 ?:是一个奇怪的操作员,有一些怪癖。认为它100% 等同于 if() { } else {}是一个常见的错误。不完全是。

在计算第一个操作数和第二个或第三个操作数之间有一个序列点。?:操作符保证只计算第2个或第3个操作数,因此它不能执行未计算的操作数的任何副作用。像 true? func1() : func2()这样的代码不会执行 func2()。目前为止,一切顺利。

但是 有一个特殊的规则,即第2个和第3个操作数必须隐式地使用 通常的算术转换进行类型提升和相互平衡。(这里解释了 C 语言中的隐式类型提升规则).这意味着第2个或第3个操作数将至少与 int一样大。

所以 truefalse碰巧是 C 中的 int类型并不重要,因为表达式总是至少给出 int的大小。

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

这是因为通过常见的算术转换实现了隐式类型提升。

在 C 中没有布尔数据类型,而是逻辑表达式计算为整数值 1,否则为 0

ifforwhile,或者 c ? 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); }

下面是源代码中包含的代码片段

#ifndef __cplusplus


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


#else /* __cplusplus */

truefalse分别声明为1和0。

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

你的 sizeof(int)是4。