Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-byte bool. Why?

In C++, why does a bool require one byte to store true or false where just one bit is enough for that, like 0 for false and 1 for true? (Why does Java also require one byte?)

Secondly, how much safer is it to use the following?

struct Bool {
    bool trueOrFalse : 1;
};

Thirdly, even if it is safe, is the above field technique really going to help? Since I have heard that we save space there, but still compiler generated code to access them is bigger and slower than the code generated to access the primitives.

like image 211
Sam Avatar asked Jan 08 '13 17:01

Sam


People also ask

Is a bool one bit?

Boolean variables are stored as 16-bit (2-byte) numbers, but they can only be True or False.

Is a boolean 1 bit or 1 byte?

no, boolean doesn't store either True or Flase. Boolean store 0 or 1. Both are single character so it takes 1 byte. You can check this by parsing it to integer.

Why is a boolean 2 bytes?

Any type of data can be assigned to Boolean variables. When assigning, non-0 values are converted to TRUE , and 0 values are converted to FALSE. When appearing as a structure member, Boolean members require 2 bytes of storage.

Why is a bool 4 bytes?

Because it's fast. A 32-bit processor typically works with 32-bit values. Working with smaller values involves longer instructions, or extra logic.


2 Answers

Why does a bool require one byte to store true or false where just one bit is enough

Because every object in C++ must be individually addressable* (that is, you must be able to have a pointer to it). You cannot address an individual bit (at least not on conventional hardware).

How much safer is it to use the following?

It's "safe", but it doesn't achieve much.

is the above field technique really going to help?

No, for the same reasons as above ;)

but still compiler generated code to access them is bigger and slower than the code generated to access the primitives.

Yes, this is true. On most platforms, this requires accessing the containing byte (or int or whatever), and then performing bit-shifts and bit-mask operations to access the relevant bit.


If you're really concerned about memory usage, you can use a std::bitset in C++ or a BitSet in Java, which pack bits.


* With a few exceptions.

like image 161
Oliver Charlesworth Avatar answered Oct 27 '22 11:10

Oliver Charlesworth


Using a single bit is much slower and much more complicated to allocate. In C/C++ there is no way to get the address of one bit so you wouldn't be able to do &trueOrFalse as a bit.

Java has a BitSet and EnumSet which both use bitmaps. If you have very small number it may not make much difference. e.g. objects have to be atleast byte aligned and in HotSpot are 8 byte aligned (In C++ a new Object can be 8 to 16-byte aligned) This means saving a few bit might not save any space.

In Java at least, Bits are not faster unless they fit in cache better.

public static void main(String... ignored) {
    BitSet bits = new BitSet(4000);
    byte[] bytes = new byte[4000];
    short[] shorts = new short[4000];
    int[] ints = new int[4000];

    for (int i = 0; i < 100; i++) {
        long bitTime = timeFlip(bits) + timeFlip(bits);
        long bytesTime = timeFlip(bytes) + timeFlip(bytes);
        long shortsTime = timeFlip(shorts) + timeFlip(shorts);
        long intsTime = timeFlip(ints) + timeFlip(ints);
        System.out.printf("Flip time bits %.1f ns, bytes %.1f, shorts %.1f, ints %.1f%n",
                bitTime / 2.0 / bits.size(), bytesTime / 2.0 / bytes.length,
                shortsTime / 2.0 / shorts.length, intsTime / 2.0 / ints.length);
    }
}

private static long timeFlip(BitSet bits) {
    long start = System.nanoTime();
    for (int i = 0, len = bits.size(); i < len; i++)
        bits.flip(i);
    return System.nanoTime() - start;
}

private static long timeFlip(short[] shorts) {
    long start = System.nanoTime();
    for (int i = 0, len = shorts.length; i < len; i++)
        shorts[i] ^= 1;
    return System.nanoTime() - start;
}

private static long timeFlip(byte[] bytes) {
    long start = System.nanoTime();
    for (int i = 0, len = bytes.length; i < len; i++)
        bytes[i] ^= 1;
    return System.nanoTime() - start;
}

private static long timeFlip(int[] ints) {
    long start = System.nanoTime();
    for (int i = 0, len = ints.length; i < len; i++)
        ints[i] ^= 1;
    return System.nanoTime() - start;
}

prints

Flip time bits 5.0 ns, bytes 0.6, shorts 0.6, ints 0.6

for sizes of 40000 and 400K

Flip time bits 6.2 ns, bytes 0.7, shorts 0.8, ints 1.1

for 4M

Flip time bits 4.1 ns, bytes 0.5, shorts 1.0, ints 2.3

and 40M

Flip time bits 6.2 ns, bytes 0.7, shorts 1.1, ints 2.4
like image 11
Peter Lawrey Avatar answered Oct 27 '22 09:10

Peter Lawrey