为什么 "sizeof(a ? true : false)" 给出四个字节的输出?
Why does "sizeof(a ? true : false)" give an output of four bytes?
我有一小段关于 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?
三元运算符 returns boolean
类型和 sizeof bool
类型在 C 中是 1
字节。
那么为什么sizeof(a ? true : false)
输出的是四个字节?
Here, ternary operator return boolean
type,
好的,还有更多内容!
在C中,this三元运算的结果是int
类型。 [下面注释(1,2)]
因此,在您的平台上,结果与表达式 sizeof(int)
相同。
注 1:引用 C11
,章节 §7.18,Boolean type and values <stdbool.h>
[....] The remaining three macros are suitable for use in #if
preprocessing directives. They
are
true
which expands to the integer constant 1,
false
which expands to the integer constant 0, [....]
注释 2:对于条件运算符,章节 §6.5.15,(强调我的)
The first operand is evaluated; there is a sequence point between its evaluation and the
evaluation of the second or third operand (whichever is evaluated). The second operand
is evaluated only if the first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second or third operand
(whichever is evaluated), [...]
和
If both the second and third operands have arithmetic type, the result type that would be
determined by the usual arithmetic conversions, were they applied to those two operands,
is the type of the result. [....]
因此,结果将是整数类型,并且由于取值范围,常量恰好是 int
类型。
也就是说,一般性建议,int main()
最好是 int main (void)
才能真正符合标准。
因为你有#include <stdbool.h>
。 header defines macros true
和 false
为 1
和 0
,因此您的语句如下所示:
printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?
sizeof(int)
在您的平台上是 4。
三元运算符是一个转移注意力的问题。
printf("%zu\n", sizeof(true));
打印 4(或您平台上的任何 sizeof(int)
)。
以下假定bool
是char
的同义词或大小为1的类似类型,int
大于char
。
之所以sizeof(true) != sizeof(bool)
和sizeof(true) == sizeof(int)
只是因为true
不是类型bool
的表达式。它是 int
类型的表达式。 #define
d 为 stdbool.h
中的 1
。
C 中根本没有 bool
类型的右值。每个这样的右值都会立即提升为 int
,即使用作 sizeof
的参数。 编辑:这一段不正确,sizeof
的参数没有得到晋升为 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
。
关于C中的boolean类型
布尔类型在 C 语言中引入的时间相当晚,在 1999 年。在此之前,C 没有布尔类型,而是对所有布尔表达式使用 int
。因此,所有逻辑运算符,例如 > == !
等 return 和值 1
或 0
的 int
。
应用程序习惯使用 home-made 类型,例如 typedef enum { FALSE, TRUE } BOOL;
,这也归结为 int
大小的类型。
C++ 有一个更好的显式布尔类型 bool
,它不大于 1 个字节。而 C 中的布尔类型或表达式在最坏的情况下最终会变成 4 个字节。 C99 标准在 C 中引入了与 C++ 兼容的某种方式。 C 然后得到一个布尔类型 _Bool
和 header stdbool.h
.
stdbool.h
提供了与 C++ 的一些兼容性。 header 定义了扩展为 _Bool
的宏 bool
(与 C++ 关键字的拼写相同),这是一种小整数类型,可能大 1 个字节。类似地,header 提供了两个宏 true
和 false
,与 C++ 关键字的拼写相同, 但向后兼容旧的 C 程序 。因此 true
和 false
在 C 中扩展为 1
和 0
,它们的类型是 int
。这些宏实际上不是像相应的 C++ 关键字那样的布尔类型。
同样,出于向后兼容的目的,C 中的逻辑运算符 仍然是 return 和 int
直到今天,即使 C 现在有布尔类型.而在 C++ 中,逻辑运算符 return a bool
。因此,像 sizeof(a == b)
这样的表达式在 C 中会给出 int
的大小,但在 C++ 中会给出 bool
的大小。
关于条件运算符?:
条件运算符 ?:
是一个奇怪的运算符,有几个怪癖。认为它 100% 等同于 if() { } else {}
是一个常见的错误。不完全是。
第一个和第二个或第三个操作数的计算之间有一个序列点。 ?:
运算符保证只评估第二个或第三个操作数,因此它不能执行未评估的操作数的任何 side-effects 。 true? func1() : func2()
之类的代码不会执行 func2()
。到目前为止,还不错。
但是,有一条特殊规则规定第二个和第三个操作数必须通过通常的算术转换[=隐式类型提升和相互平衡。 (Implicit type promotion rules in C explained here)。这意味着第二个或第三个操作数将 始终 至少与 int
.
一样大
所以 true
和 false
恰好是 C 中的 int
类型并不重要,因为表达式总是至少给出 [=10] 的大小=] 不管。
即使您将表达式重写为 sizeof(a ? (bool)true : (bool)false)
它仍然 return 一个 int
的大小!
这是因为通过通常的算术转换进行了隐式类型提升。
C 中没有布尔数据类型,逻辑表达式的计算结果为整数值 1
否则 0
.
if
、for
、while
或 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 */
宏true
和false
分别声明为1和0。
但是在这种情况下,类型是文字常量的类型。 0和1都是整型常量,适合int,所以它们的类型都是int。
而你的 sizeof(int)
是 4.
我有一小段关于 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?
三元运算符 returns boolean
类型和 sizeof bool
类型在 C 中是 1
字节。
那么为什么sizeof(a ? true : false)
输出的是四个字节?
Here, ternary operator return
boolean
type,
好的,还有更多内容!
在C中,this三元运算的结果是int
类型。 [下面注释(1,2)]
因此,在您的平台上,结果与表达式 sizeof(int)
相同。
注 1:引用 C11
,章节 §7.18,Boolean type and values <stdbool.h>
[....] The remaining three macros are suitable for use in
#if
preprocessing directives. They are
true
which expands to the integer constant 1,
false
which expands to the integer constant 0, [....]
注释 2:对于条件运算符,章节 §6.5.15,(强调我的)
The first operand is evaluated; there is a sequence point between its evaluation and the evaluation of the second or third operand (whichever is evaluated). The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), [...]
和
If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result. [....]
因此,结果将是整数类型,并且由于取值范围,常量恰好是 int
类型。
也就是说,一般性建议,int main()
最好是 int main (void)
才能真正符合标准。
因为你有#include <stdbool.h>
。 header defines macros true
和 false
为 1
和 0
,因此您的语句如下所示:
printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?
sizeof(int)
在您的平台上是 4。
三元运算符是一个转移注意力的问题。
printf("%zu\n", sizeof(true));
打印 4(或您平台上的任何 sizeof(int)
)。
以下假定bool
是char
的同义词或大小为1的类似类型,int
大于char
。
之所以sizeof(true) != sizeof(bool)
和sizeof(true) == sizeof(int)
只是因为true
不是类型bool
的表达式。它是 int
类型的表达式。 #define
d 为 stdbool.h
中的 1
。
C 中根本没有 编辑:这一段不正确,bool
类型的右值。每个这样的右值都会立即提升为 int
,即使用作 sizeof
的参数。sizeof
的参数没有得到晋升为 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
。
关于C中的boolean类型
布尔类型在 C 语言中引入的时间相当晚,在 1999 年。在此之前,C 没有布尔类型,而是对所有布尔表达式使用 int
。因此,所有逻辑运算符,例如 > == !
等 return 和值 1
或 0
的 int
。
应用程序习惯使用 home-made 类型,例如 typedef enum { FALSE, TRUE } BOOL;
,这也归结为 int
大小的类型。
C++ 有一个更好的显式布尔类型 bool
,它不大于 1 个字节。而 C 中的布尔类型或表达式在最坏的情况下最终会变成 4 个字节。 C99 标准在 C 中引入了与 C++ 兼容的某种方式。 C 然后得到一个布尔类型 _Bool
和 header stdbool.h
.
stdbool.h
提供了与 C++ 的一些兼容性。 header 定义了扩展为 _Bool
的宏 bool
(与 C++ 关键字的拼写相同),这是一种小整数类型,可能大 1 个字节。类似地,header 提供了两个宏 true
和 false
,与 C++ 关键字的拼写相同, 但向后兼容旧的 C 程序 。因此 true
和 false
在 C 中扩展为 1
和 0
,它们的类型是 int
。这些宏实际上不是像相应的 C++ 关键字那样的布尔类型。
同样,出于向后兼容的目的,C 中的逻辑运算符 仍然是 return 和 int
直到今天,即使 C 现在有布尔类型.而在 C++ 中,逻辑运算符 return a bool
。因此,像 sizeof(a == b)
这样的表达式在 C 中会给出 int
的大小,但在 C++ 中会给出 bool
的大小。
关于条件运算符?:
条件运算符 ?:
是一个奇怪的运算符,有几个怪癖。认为它 100% 等同于 if() { } else {}
是一个常见的错误。不完全是。
第一个和第二个或第三个操作数的计算之间有一个序列点。 ?:
运算符保证只评估第二个或第三个操作数,因此它不能执行未评估的操作数的任何 side-effects 。 true? func1() : func2()
之类的代码不会执行 func2()
。到目前为止,还不错。
但是,有一条特殊规则规定第二个和第三个操作数必须通过通常的算术转换[=隐式类型提升和相互平衡。 (Implicit type promotion rules in C explained here)。这意味着第二个或第三个操作数将 始终 至少与 int
.
所以 true
和 false
恰好是 C 中的 int
类型并不重要,因为表达式总是至少给出 [=10] 的大小=] 不管。
即使您将表达式重写为 sizeof(a ? (bool)true : (bool)false)
它仍然 return 一个 int
的大小!
这是因为通过通常的算术转换进行了隐式类型提升。
C 中没有布尔数据类型,逻辑表达式的计算结果为整数值 1
否则 0
.
if
、for
、while
或 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 */
宏true
和false
分别声明为1和0。
但是在这种情况下,类型是文字常量的类型。 0和1都是整型常量,适合int,所以它们的类型都是int。
而你的 sizeof(int)
是 4.