【问题标题】:Defining smallest possible sized macro in C在 C 中定义最小可能大小的宏
【发布时间】:2013-05-17 20:12:05
【问题描述】:

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

编辑:

当我定义一个宏时

#define True 0
#define False !True

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

编辑2:

我刚刚阅读了有关 bitpacking 的内容,但是我可以将一点点用于布尔值是最好的。我只是不太确定如何对只有几位大小的打击进行位打包。

编辑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

【问题讨论】:

  • 如何定义宏的大小?
  • 您在寻找char(或int8_t)吗?
  • 越小效率越高。字节在现代处理器上非常低效 32 或 64 位大小的值(寄存器的大小)是最有效的大小。 x86 有 8 位和 16 位以及 32 位和 64 位大小的寄存器,因此从这个角度来看,一个字节还不错,然后它会为了效率而进入总线传输(如果在 ram 中),并且单个字节的成本与更大的寄存器相同,因此无需努力让那个小..
  • 避免使用 64 位整数的唯一原因是我的程序可以使用 26 GB 以上的 RAM。
  • 当人们需要更高效地表示某事时,称他们为愚蠢是愚蠢的。

标签: c gcc assembly macros


【解决方案1】:

为你的宏试试这个:

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

【讨论】:

  • 我试过这个;但是,当我有 if 语句 if (True) { /* Do Something */}
  • 因为我的宏是倒退的——我跛脚。固定。
  • 注意,应该是#define true (!false)
  • 我的编译器还是不喜欢这个,让我编辑我原来的帖子给你看。
  • 那些宏并不是特别有用——第一个是语法错误(你的转换语法错误)。他们为truefalse 指定;对这些值的任何使用都将转换为某种存储格式,无论如何您都必须对其进行定义。写#define true 1#define false 0 更清晰,同样好——如果你有#include &lt;stdbool.h&gt;,即使这样也没有必要。
【解决方案2】:

首先,没有与您的宏关联的存储;它们扩展为整数 constants 01sizeof 的计算结果为 4,因为 表达式 具有整数类型。您当然可以将这些值分配给较小类型的对象(shortchar)。

对我来说,当我停止使用 TRUEFALSE1 时,生活变得简单多了。请记住,在 C 中,零值积分表达式的计算结果为 false,所有非零值积分表达式的计算结果为 true。

如果您想将值存储到小于 8 位的内容中,那么您将不得不自己进行位打包,例如

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

对此有用的最小类型是unsigned char。因此,如果您需要存储 N 个单位值,则需要一个包含 N/CHAR_BIT+1 个元素的数组。例如,要存储 10 个单位布尔值,您需要 2 个八位数组元素。位 0 到 7 将存储在元素 0 中,位 8 到 10 将存储在元素 1 中。

所以,像

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

没有明示或暗示的保证;我不会做太多的玩弄。但希望这至少可以为您指明正确的方向。


1。促成事件是有人在TRUE == FALSE 处删除了一个标题。不是效率最高的下午。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      typedef unsigned char smallBool;
      
      smallBool boolMatrix[M][N];
      

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

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

      【讨论】:

      • 他们将如何评估 if 语句?例如,假设我想查看第 i 行和第 j 列并说 if (boolMatrix[i][j]) { return 1}
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多