簡體   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