一字节布尔。为什么?

2022-09-01 01:45:43

在C++中,为什么一个 bool 需要一个字节来存储 true 或 false,而只有一个位就足够了,比如 0 表示 false,1 表示 true?(为什么Java也需要一个字节?

其次,使用以下内容有多安全?

struct Bool {
    bool trueOrFalse : 1;
};

第三,即使它是安全的,上述现场技术真的会有所帮助吗?由于我听说我们在那里节省了空间,但是编译器生成的代码仍然比用于访问基元的代码更大,更慢。


答案 1

为什么 bool 需要一个字节来存储 true 或 false,而只有一个位就足够了

因为C++中的每个对象都必须是可单独寻址的*(也就是说,您必须能够有一个指向它的指针)。您无法寻址单个位(至少在传统硬件上不能)。

使用以下命令的安全性有多高?

它是“安全的”,但它并没有取得多大成就。

上述现场技术真的会有所帮助吗?

不,出于与上述相同的原因;)

但是编译器生成的代码仍然比访问它们的代码更大,更慢,而不是为访问基元而生成的代码。

是的,这是真的。在大多数平台上,这需要访问包含字节(或其他),然后执行位移和位掩码操作来访问相关位。int


如果您真的担心内存使用情况,则可以在C++中使用std::bitset或在Java中使用BitSet,它包含位。


* 除少数例外情况外。


答案 2

使用单个位的速度要慢得多,分配起来也要复杂得多。在C / C++没有办法获得一个位的地址,所以你将无法做一点。&trueOrFalse

Java有一个BitSet和EnumSet,它们都使用位图。如果你的数字非常小,它可能不会有太大的区别。例如,对象必须至少是字节对齐的,并且在HotSpot中是8字节对齐的(C++对象可以是8到16字节对齐的),这意味着节省几个位可能不会节省任何空间。new

至少在Java中,Bits不会更快,除非它们更适合缓存。

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;
}

指纹

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

适用于 40000 和 400K 的尺寸

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

适用 4M

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

和40M

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

推荐