为x位分配n个字节

时间:2010-11-04 20:16:59

标签: c bit-manipulation

首先,这可以是任何语言的通用算法,但我正在学习C,如果有一些C特定的功能,我想知道!

我正在编写一个函数,它将为给定的位数分配足够的内存;到long long *变量。位数不能是< 1。我测试了算法:

int bits;  // the function argument, checked for value > 0
size_t dataSize;  // the value passed to the malloc function

for (bits = 1; bits<100; bits++) {
   if (bits < sizeof(long long)) {
      dataSize = 1;
   } else {
      dataSize = (bits + (sizeof(long long) - (bits % sizeof(long long)))) / sizeof(long long);
   }

   printf("%d = %d\n", bits, (int) dataSize);
}

看起来不错......但很难看:) 有没有办法以更优雅的方式实现这一目标? 谢谢!

8 个答案:

答案 0 :(得分:2)

假设您要将位字段初始化为零,calloc()可能优于malloc();你可能也应该使用无符号类型来避免在比特位时使用有符号的移位。

#include <limits.h>

const size_t BITS_PER_BLOCK = sizeof (long long) * CHAR_BIT;
size_t count = bits / BITS_PER_BLOCK + !!(bits % BITS_PER_BLOCK);
unsigned long long *blocks = calloc(count, sizeof *blocks);

!!是一种将非零值转换为1的有点h​​ackish方式,这在C中很常见,如果位数不能被{整除,则用于分配一个额外的块{1}}。

你也可以通过

获得所需数量的积分(其中包括Lars在评论中指出的另一个答案)
BITS_PER_BLOCK

我发现前一版本更具可读性,但后者也很常见 - 这是使用整数算术的更通用的舍入算法的特例 - C程序员应该对这两种选择都感到满意。

答案 1 :(得分:1)

除非我遗漏了什么,否则我认为它只会是:

int bits;
size_t dataSize;

dataSize = bits / (sizeof(long long) * 8);
if( bits % (sizeof(long long) * 8) ) { //Don't add 1 if it was evenly divisible
    dataSize++;
}
dataSize *= sizeof(long long)

因此假设long long大小为8个字节,值为1-64将返回8,65-128将返回16,等等。

答案 2 :(得分:1)

如果你想要n位,那么计算long long量的正确表达式是:

int bits = n;
int items = (((bits - 1) / CHAR_BIT) / sizeof(long long)) + 1;

答案 3 :(得分:0)

你不应该需要一个循环。如果你进行了bits / sizeof(long long)的除法,你应该得到一个向下舍入的结果。然后,您可以通过执行比特模数%sizeof(long long)检查余数,如果它不为零,则需要在结果中添加一个。

答案 4 :(得分:0)

size_t len_needed(int bits) {
   size_t x=  bits/(sizeof(long long) * 8);
   x = (bits%(sizeof(long long) * 8) ? 1 : 0;

   return x;
}

? :只是三元运算符,这是执行if / else计算结果值的简短方法。

答案 5 :(得分:0)

这是您的代码,只有一个新值添加到printf

int bits;  // the function argument, checked for value > 0
size_t dataSize;  // the value passed to the malloc function

for (bits = 1; bits<100; bits++) {
   if (bits < sizeof(long long)) {
      dataSize = 1;
   } else {
      dataSize = (bits + (sizeof(long long) - (bits % sizeof(long long)))) / sizeof(long long);
   }

   printf("%d = %d (%d)\n", bits, (int) dataSize, 1 + bits/sizeof (long long));
   /*             ^^^^^                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
}

答案 6 :(得分:0)

#define SIZEOF_LL  sizeof(long long)
nbytes  =  (xbits  + 8         - 1) / 8;
nllongs =  (nbytes + SIZEOF_LL - 1) / SIZEOF_LL;

或者如果您知道尺寸。

nbytes =  (xbits  + 7) / 8;
nllongs = (nbytes + 7) / 8;

答案 7 :(得分:0)

Number_of_long_longs_for_x= (x + sizeof(long long) - 1)/sizeof(long long)

现在,long long中的位数为log2(ULLONG_MAX+1),而不是sizeof(long long)。所以你应该重新考虑你的计算。