简单的示例程序:
#include <stdio.h>
main()
{
bool tim = true;
bool rob = false;
bool mike = true;
printf("%d, %d, %d\n", tim, rob, mike);
}
使用gcc编译器,根据查看程序集输出,它的出现者将每个bool存储为单个字节中的位:
0x4004fc <main()+8> movb $0x1,-0x3(%rbp)
0x400500 <main()+12> movb $0x0,-0x2(%rbp)
0x400504 <main()+16> movb $0x1,-0x1(%rbp)
但是,如果一个开启优化,是否有一个优化级别会导致gcc将这些bool存储为一个字节中的位,或者是否必须将bool放在某些bool和short int的并集中?其他编译器?我试过'-Os',但我必须承认我无法对输出反汇编做出正面或反面。
答案 0 :(得分:7)
编译器可以执行它喜欢的任何转换,只要程序的结果行为不受影响,或者至少在允许的行为范围内。
这个程序:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
bool tim = true;
bool rob = false;
bool mike = true;
printf("%d, %d, %d\n", tim, rob, mike);
}
(我已经修改了一些使其有效)可以优化到相当于此,因为行为是相同的:
#include <stdio.h>
int main(void)
{
puts("1, 0, 1");
}
因此,三个bool
对象不仅存储在单个位中,而且根本不存储它们。
编译器可以自由地玩这样的游戏,只要它们不影响可见行为即可。例如,由于程序从不使用三个bool
变量的地址,并且从不引用它们的大小,因此编译器可以选择将它们全部存储为单个字节中的位。 (没有理由这样做;访问单个位所需的代码大小的增加将超过任何数据大小的节省。)
但这种积极的优化可能不是你所要求的。
在“抽象机器”中,bool
对象必须至少为一个字节,除非它是一个位字段。
除了位字段之外的bool
对象或任何对象必须具有唯一的地址,并且其大小必须是1字节的整数倍。如果打印sizeof (bool)
或sizeof tim
的值,结果将至少为1.如果打印三个对象的地址,它们将是唯一的,至少相隔一个字节。
答案 1 :(得分:1)
你不会使用bools联合。相反,你可以说
struct a
{
unsigned char tim : 1;
unsigned char rob : 1;
unsigned char mike : 1;
} b;
b.tim=1;
b.rob=0;
b.mike=1;
它将全部存储在一个char中。但是,你不能保证它在内存中的排列方式或它是如何对齐的。
答案 2 :(得分:1)
@Keith Thompson的好答案可以解释问题中代码示例的情况。但我会假设编译器没有转换程序。根据标准,bool
(stdbool.h
中与关键字_Bool
相同的宏)的大小必须为一个字节。
C99 6.2.6.1 一般
除了位字段,对象由一个或多个字节的连续序列组成, 其数量,顺序和编码是明确指定的 实现定义的。
这意味着对象的任何类型(除了位字段,包括bool
)必须至少一个字节。
C99 6.3.1.1 布尔,字符和整数
等级_Bool应小于所有其他标准整数类型的等级。
这意味着bool
的大小不超过char
(这是一个整数类型)。我们也知道char
的大小保证是一个字节。因此,bool
的大小应该最多一个字节。
结论:bool
的大小必须是一个字节。