5

trivial example program:

#include <stdio.h>
main()
{
    bool tim = true;
    bool rob = false;
    bool mike = true;

    printf("%d, %d, %d\n", tim, rob, mike);

}

Using the gcc compiler it appearers, based on looking at the assembly output, that each bool is stored as a bit in individual bytes:

0x4004fc <main()+8>          movb      $0x1,-0x3(%rbp)
0x400500 <main()+12>         movb      $0x0,-0x2(%rbp)
0x400504 <main()+16>         movb      $0x1,-0x1(%rbp)

if, however, one turns optimization on, is there a level of optimization that will cause gcc to store these bools as bits in a byte or would one have to put the bools in a union of some bools and a short int? Other compilers? I have tried '-Os' but I must admit I can't make heads or tails of the output disassembly.

4

3 回答 3

7

A compiler can perform any tranformations it likes, as long as the resulting behavior of the program is unaffected, or at least within the range of permitted behaviors.

This program:

#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);

}

(which I've modified a bit to make it valid) could be optimized to the equivalent of this, since the behavior is identical:

#include <stdio.h>
int main(void)
{
    puts("1, 0, 1");
}

So the three bool objects aren't just stored in single bits, they're not stored at all.

A compiler is free to play games like that as long as they don't affect the visible behavior. For example, since the program never uses the addresses of the three bool variables, and never refers to their sizes, a compiler could choose to store them all as bits within a single byte. (There's little reason to do so; the increase in the size of the code needed to access individual bits would outweigh any savings in data size.)

But that kind of aggressive optimization probably isn't what you're asking about.

In the "abstract machine", a bool object must be a least one byte unless it's a bit field. A bool object, or any object other than a bit field, must have an unique address, and must have a size that's a whole multiple of 1 byte. If you print the value of sizeof (bool) or sizeof tim, the result will be at least 1. If you print the addresses of the three objects, they will be unique and at least one byte apart.

于 2013-07-26T16:28:11.510 回答
1

You would not use a union of bools. Instead you can say

struct a
{
unsigned char tim : 1;
unsigned char rob : 1;
unsigned char mike : 1;
} b;

b.tim=1;
b.rob=0;
b.mike=1;

and it would all get stored in a single char. However, you would not have any guarantees about how it's layed out in memory or how it's aligned.

于 2013-07-26T16:32:54.917 回答
1

@Keith Thompson's good answer can explain what happened with the code example in the question. But I'll assume that the compiler doesn't transform the program. According to the standard, a bool (a macro in stdbool.h the same as the keyword _Bool) must have a size of one byte.

C99 6.2.6.1 General

Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.

This means that any type(except bit-fields, including bool) of objects must have at least one byte.

C99 6.3.1.1 Boolean, characters, and integers

The rank of_Bool shall be less than the rank of all other standard integer types.

This means bool's size is no more than a char(which is an integer type). And we also know that the size of an char is guaranteed to be one byte. So the size of bool should be at most one byte.

Conclusion: the size of bool must be one byte.

于 2013-07-26T17:01:17.737 回答