我有一小段关于sizeof运算符和三元运算符的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <stdio.h>
#include <stdbool.h>
int main ()
{
bool a = true;
printf("%zu
", sizeof(bool )); // Ok
printf("%zu
", sizeof(a )); // Ok
printf("%zu
", sizeof(a ? true : false)); // Why 4?
return 0;
} |
输出(GCC):
但在这里,
1 2
| printf("%zu
", sizeof(a ? true : false)); // Why 4? |
三元运算符返回boolean类型,bool类型的sizeof为c中的1字节。
那么,为什么sizeof(a ? true : false)给出4个字节的输出?
- 另见:IDE.geeksforgeeks.org/o5jvun。
- 如果它是EDOCX1,2,那么它是正确的,因为EDOCX1,3和EDOCX1,4是整合常数。
- @VU1P3N0X note the wording"integer constant"doesn't require a specific integer type.可按((char)1)和((char)0)的定义。
- 这里最感兴趣的问题是,为什么这一执行是"不一致的",因为它明显地定义了_Bool的尺寸,而不是true和false。但标准没有什么要说的只要我能说的远就行了But the standard doesn't have anything to say about that as far as I can tell.
- 费利克斯帕尔曼和埃多克斯1〔14〕的原因相同。这不是关于执行,而是关于语言。
- 是一种int常数,其中true是一个宏观定义的整合常数。我在这里看到了一个不同的地方,但它肯定是关于你如何解释这个词。
- @Felixpalmen,这和你说的有什么不同?我看不见任何人在预处理后,1是一种int型常数,就像'a'。
- 你试过打印吗?也许它会使事情变得更清晰(特别是,它会显得三元算子是红色的Herring)。
- @n.m.I'm referring to the ambiguity of the term"integer constant",that doesn't force the type to be int如果你读到1的文献定义(我不确定这是可以解释的),那么这类人就是int。
- 是的,这是文学定义。
- -=Felixpalmen what ambiguity?Integer Constants are defined in section 6.4.4.1(whose name is"Integer Constants"),and their types are specified in&;-167;5.这是最起码的指数(EDOCX1,29)
- @Virgile Well,as a lexical element,yes.我同意这可能意味着什么,但这并不重要,因为一个#define true ((_Bool)1)〔31〕你不会买任何东西,给你隐含的转变和整合促进。然而,即使是"整合常数"的一章,在"语义"部分也有矛盾。
- 也将打印出4,使这个问题更加有趣。
- Relevant…
- 这是一个完美的问题,不应该是投票-对-封闭的太大(目前有2票)。
- 在STDBOOL.H TRUE也是一个整体。。。注:
这是因为你有#include 。该头将宏true和false定义为1和0,因此您的语句如下:
1 2
| printf("%zu
", sizeof(a ? 1 : 0)); // Why 4? |
sizeof(int)在您的平台上是4。
- "这是因为您有include"不,它不是。sizeof(a ? (uint8_t)1 : (uint8_t)0);也会给出4的结果。?:操作数的整数提升是这里的重要部分,而不是true和false的大小。
- @伦丁:两者都很重要。如前所述,类型已经是int,没有提升。你不能"修复"它的原因是默认的促销。
- 这不是C++。这是C++中的C.,EDCOX1,4,EDCOX1,5,不是宏,它们是关键字。它们不是被定义为1和0,而是bool类型的真值和假值。
- @彼得施耐德,不,你今天学到了一些关于C的知识。不要混淆这两种语言。在C++中,EDOCX1×12是1。演示。
- 是的,把它弄混了。没有仔细阅读,被CPPCreference链接误导。我的错,谢谢。但不管怎样,我对C++有这种感觉。
Here, ternary operator return boolean type,
好吧,还有更多!
在C语言中,这种三元运算的结果是int类型。[以下注释(1,2)]
因此,结果与平台上的表达式sizeof(int)相同。
注1:引用C11,第7.18章,Boolean type and values
[....] 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章(重点是Mine)
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. [....]
因此,结果将是integer类型,并且由于值范围的原因,这些常量正好是int类型。
也就是说,一个通用的建议,int main()最好是int main (void)真正符合标准。
- @用户694733嗯……为什么不呢?将宏定义为int类型。这是错误的吗?
- @巴兹勒斯特林凯维奇好吧,我现在看到了,这似乎确实是错误的,现在更新。
三元运算符是一个红鲱鱼。
打印4(或任何平台上的EDOCX1[1])。
下面假设bool是char或类似类型的1号的同义词,并且int大于char。
sizeof(true) != sizeof(bool)和sizeof(true) == sizeof(int)的原因仅仅是因为true不是bool型的表达。它是int类型的表达式。它是#defined,在stdbool.h中是1d。
在c中根本没有bool类型的rvalues。每一个这样的值都会立即提升为int,即使当用作sizeof的参数时也是如此。〔s〕edit:This paragraph is not true,arguments to sizeofdon't get promoted to int。但这并不影响任何结论。
- 很好的回答。在我阅读了目前最乐观的答案之后,我想所有的陈述都应该评估为4。这就解决了问题。+ 1
- (bool)1不是bool类型的右值吗?
- printf("%u
", sizeof((char) 1));在我的平台上打印1,而printf("%u
", sizeof(1));打印4。这是否意味着您的语句"即使用作sizeof的参数,也会立即将每个这样的右值提升为int"为false?
- @你说得对,我的记忆有点小问题。
- 这并不能真正回答问题。在?:的情况下,true等的大小和类型实际上并不重要,因为它无论如何都被提升为int的整数。也就是说,答案应该说明为什么?:是一条红鲱鱼。
- @伦丁一旦你知道了sizeof(true)==sizeof(int),你还会想知道为什么是sizeof(1?true:false) == sizeof(int)?是否需要单独解释?
- 好。。。例如,在C++中去掉EDCOX1的25编译,其中真和假的大小是1。仍然是结果4。
- @lundin问题是关于c的,而不是任何以c开头的语言。
- 所以在C语言中编译sizeof(1?(char)true:(char)false)。同样的问题。
- @lundin这个问题没有问关于sizeof(1?(char)true:(char)false)的问题。它询问有关sizeof(a ? true : false)的问题。我就是这么回答的。
- 让我们在聊天中继续讨论。
- 我认为答案以最好的方式解决了这个问题。欢迎你投反对票或改进它。
- sizeof()通常不评价它的论点,所以这意味着它不促进它们的发展。它从字面上取( )中表达式的字节大小。不过,当sizeof()确实评估了它的论点时,有一个例外。stackoverflow.com/a/47336577/5500589号
关于C中的布尔类型
1999年,布尔类型在C语言中引入得相当晚。在此之前,C没有布尔类型,而是将int用于所有布尔表达式。因此,所有逻辑运算符(如> == !等)都返回值为1或0的int。
应用程序使用自制类型(如typedef enum { FALSE, TRUE } BOOL;)是定制的,也可以归结为int大小的类型。
C++有一个更好的,明确的布尔类型,EDOCX1×7,不大于1字节。而在最坏的情况下,C中的布尔类型或表达式将以4个字节结束。在C99标准中,C++中引入了一些与C++兼容的方式。然后,C得到一个布尔型_Bool,以及头部stdbool.h。
EDOCX1 9提供了与C++的一些兼容性。这个标头定义了宏EDCOX1的7个字(与C++关键字相同的拼写),扩展到EDCOX1×8,类型是一个小整数类型,可能有1个字节大。类似地,报头提供两个宏EDOCX1,13和EDCOX1,14,同样的拼写作为C++关键字,但与旧C程序向后兼容。因此,true和false在c中扩展到1和0,其类型为int。这些宏实际上不是像相应的C++关键字那样的布尔类型。
同样,为了向后兼容的目的,C中的逻辑运算符至今仍返回int,尽管C现在有一个布尔类型。在C++中,逻辑运算符返回EDCOX1×7Ω。因此,一个表达式如EDCOX1(22)将在C中给出EDCOX1×0的大小,但是在C++中EDCOX1的大小为7。
关于条件运算符?:。
条件运算符?:是一个奇怪的运算符,有两个奇怪的地方。认为100%等同于if() { } else {}是一个常见的错误。不完全是这样。
在第一个操作数和第二个或第三个操作数的计算之间有一个序列点。保证?:运算符只计算第二个或第三个操作数,因此它不能执行未计算的操作数的任何副作用。像true? func1() : func2()这样的代码不会执行func2()。到目前为止,一切都很好。
但是,有一个特殊的规则指出,第二个和第三个操作数必须通过通常的算术转换隐式地升级类型并相互平衡。(此处解释了C中的隐式类型提升规则)。这意味着第二个或第三个操作数总是至少与int一样大。
因此,true和false恰好是c中的int类型并不重要,因为表达式总是至少给出int的大小。
即使将表达式重写为sizeof(a ? (bool)true : (bool)false),它仍将返回int的大小!
这是因为通过通常的算术转换实现了隐式类型提升。
- C++实际上并不能保证EDCOX1×38Ω。
- 但是,在C++标准之外的真实世界确实保证了这一点。命名一个不是1的编译器。
- 你好。我认为没有第一部分这个答案会更好。第二部分回答了这个问题。其余的虽然有趣,但只是噪音。
- YSC最初是用C和C++来标记的,所以比较它们的不同类型和它们背后的历史是必要的。我怀疑如果不是C++标签,我会写第一部分。然而,我们必须理解为什么sizeof(bool)是1,而sizeof(false)是4。
- 我理解。。。
快速回答:
- sizeof(a ? true : false)计算为4,因为true和false在中分别定义为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++对EDCOX1、14的类型、布尔值EDCOX1、8和EDCOX1、9、比较算子和三元算子有不同的语义:所有这些EDCOX1×63表达式在C++中被评估为EDCOX1×10。
- 很好的答案是,实际上能够指出什么类型的true和false并不重要,因为?:操作数无论如何都会被提升为int的整数。因此,sizeof(a ? (uint8_t)true : (uint8_t)false)也将产生4个。
- 这个答案涵盖了主要的要点,价值提升到EDOCX1[1]
以下是源代码中包含的代码段
1 2 3 4 5 6 7
| #ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#else /* __cplusplus */ |
宏true和false分别声明为1和0。
但是在这种情况下,类型是文本常量的类型。0和1都是整型常量,适合于int,所以它们的类型是int。
在你的情况下,sizeof(int)是4。
C中没有布尔数据类型,而逻辑表达式的计算结果为整数值1,否则为true,否则为0。
条件表达式,如if、for、while或c ? a : b期望一个整数,如果数字为非零,则认为true,除某些特殊情况外,这里有一个递归和函数,三元运算符将对true进行计算,直到n达到0。
1
| int sum (int n) { return n ? n+sum(n-1) : n ; |
它还可以用于NULL检查指针,这里有一个递归函数,用于打印单个链接列表的内容。
1
| void print (sll * n ){ printf("%d ->",n ->val ); if(n ->next )print (n ->next ); } |