繁体   English   中英

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

[英]storage of bool in c under various compilers and optimization levels

简单的示例程序:

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

只要程序的结果行为不受影响,或者至少在允许的行为范围内,编译器就可以执行它喜欢的任何转换。

这个程序:

#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.如果打印三个对象的地址,它们将是唯一的,并且至少相隔一个字节。

你不会使用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中。 但是,你不能保证它在内存中的布局方式或它是如何对齐的。

@Keith Thompson的好答案可以解释问题中代码示例发生了什么。 但我会假设编译器不会转换程序。 根据标准, boolstdbool.h的宏与关键字_Bool相同)必须具有一个字节的大小。

C99 6.2.6.1 概述

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

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

C99 6.3.1.1 布尔,字符和整数

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

这意味着bool的大小不超过char (这是一个整数类型)。 而且我们也知道char的大小保证是一个字节。 所以bool的大小最多只能一个字节。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM