-1

我想在 C 中定义一个使用少于 4 个字节的布尔宏。我已经对此进行了研究,也许可以使用 gcc 定义一个 asm 宏,它可能会更少。定义要小很重要,因为我将拥有数以万计的矩阵来保存这些布尔值,重要的是它们可以尽可能地节省内存。理想情况下,我想定义一个代表真假的 4 位或 8 位宏,并将在 if 语句中进行评估。

编辑:

当我定义一个宏

#define True 0
#define False !True

然后打印大小,它返回一个4字节的大小,效率很低。

编辑2:

我刚刚阅读了有关位打包的内容,但是对于布尔值而言,无论我能拥有多少位都是最好的。我只是不太确定如何对具有几位大小的打击进行位打包。

编辑3:

#include <stdio.h>
#include <string.h>

#define false (unsigned char(0))
#define true (!false)

int main() {
    if (true) {
        printf("The size of true is %d\n", sizeof(true));
    }
}

给出以下输出

test.c: In function ‘main’:
test.c:8:9: error: expected ‘)’ before numeric constant
test.c:9:51: error: expected ‘)’ before numeric constant
4

4 回答 4

4

试试这个代替你的宏:

#define false ((unsigned char) 0)
#define true (!false)

不过,这并不能解决您的空间需求。为了更有效的存储,您需要使用位:

void SetBoolValue(int bitOffset, unsigned char *array, bool value)
{
    int index = bitOffset >> 3;
    int mask = 1 << (bitOffset & 0x07);

    if (value)
        array[index] |= mask;
    else
        array[index] &= ~mask;
}

bool GetBoolValue(int bitOffset, unsigned char *array)
{
    int index = bitOffset >> 3;
    int mask = 1 << (bitOffset & 0x07);

    return array[index] & mask;
}

“数组”的每个值可以容纳 8 个布尔值。在现代系统上,使用 U32 或 U64 作为阵列会更快,但它可能会占用更多空间来存储更少量的数据。

打包大量数据:

void SetMultipleBoolValues(int bitOffset, unsigned char *array, int value, int numBitsInValue)
{
    for(int i=0; i<numBitsInValue; i++)
    {
        SetBoolValue(bitOffset + i, array, (value & (1 << i)));
    }
}

这将是一个驱动程序:

int main(void)
{
    static char array[32];  // Static so it starts 0'd.
    int value = 1234;  // An 11-bit value to pack

    for(int i=0; i<4; i++)
        SetMultipleBoolValues(i * 11, array, value, 11);  // 11 = 11-bits of data - do it 4 times

    for(int i=0; i<32; i++)
       printf("%c", array[i]);

    return 0;
}
于 2013-05-22T17:01:45.103 回答
1

如果您在结构中使用它,那么您将需要使用位字段。

struct {
    unsigned flag : 1;
    /* other fields */
};

如果你想要一个布尔值数组,你应该实现一个位向量(我正要实现一个,但 Michael Dorgan 已经做到了)。

于 2013-05-22T17:07:56.430 回答
1

First of all, there's no storage associated with your macros; they expand to the integer constants 0 and 1. The sizeof evaluates to 4 because the expressions have integer type. You can certainly assign those values to objects of smaller type (short or char).

For me, life got a lot simpler when I stopped using TRUE and FALSE macros1. Remember that in C, a zero-valued integral expression evaluates to false, and all non-zero-valued integral expressions evaluate to true.

If you want to store values into something smaller than 8 bits, then you're going to have to do your own bit packing, something like

#define TEST(x,bit) ((x) & (1 << (bit)))
#define SET(x,bit) ((x) |= (1 << (bit)))
#define CLEAR(x,bit) ((x) &= ~(1 << (bit)))  

The smallest useful type for this is unsigned char. So if you need to store N single-bit values, you need an array of N/CHAR_BIT+1 elements. For example, to store 10 single-bit boolean values, you need 2 eight-bit array elements. Bits 0 through 7 will be stored in element 0, and bits 8 through 10 will be stored in element 1.

So, something like

#define MAX_BITS 24
unsigned char bits[MAX_BITS / CHAR_BIT + 1];

int bit = ...;

SET(bits[bit/CHAR_BIT], bit % CHAR_BIT);

if ( TEST(bits[bit/CHAR_BIT], bit % CHAR_BIT) )
{
  // do something if bit is set
}

CLEAR(bits[bit/CHAR_BIT], bit % CHAR_BIT);

No warranties express or implied; I don't do a lot of bit twiddling. But hopefully this at least points you in the right direction.


1. The precipitating event was someone dropping a header where TRUE == FALSE. Not the most productive afternoon.

于 2013-05-22T18:07:40.650 回答
0

您可能应该只使用一个unsigned char,它将是最小的可单独寻址的类型:

typedef unsigned char smallBool;

smallBool boolMatrix[M][N];

以上将使用M * N字节作为矩阵。

当然,浪费CHAR_BIT - 1位来存储单个位是……浪费。考虑对布尔值进行位打包。

于 2013-05-22T16:57:08.167 回答