在各种编译器和优化级别下在c中存储bool

时间:2013-07-26 16:08:17

标签: c gcc compiler-construction icc

简单的示例程序:

#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',但我必须承认我无法对输出反汇编做出正面或反面。

3 个答案:

答案 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的好答案可以解释问题中代码示例的情况。但我会假设编译器没有转换程序。根据标准,boolstdbool.h中与关键字_Bool相同的宏)的大小必须为一个字节。

C99 6.2.6.1 一般

  

除了位字段,对象由一个或多个字节的连续序列组成,   其数量,顺序和编码是明确指定的   实现定义的。

这意味着对象的任何类型(除了位字段,包括bool)必须至少一个字节。

C99 6.3.1.1 布尔,字符和整数

  

等级_Bool应小于所有其他标准整数类型的等级。

这意味着bool的大小不超过char(这是一个整数类型)。我们也知道char的大小保证是一个字节。因此,bool的大小应该最多一个字节。

结论:bool的大小必须是一个字节。