我可以在 C 中分配特定数量的位数吗?
我试图存储在运行时确定的大量布尔信息。 我想知道最好的方法是什么。
我目前一直在尝试使用以下方式分配内存:
pStatus = malloc((<数据点数量>/8) + 1);
认为这将为我提供足够的位来使用。 然后,我可以使用数组表示法中的指针引用每个布尔值:
pStatus[element]
不幸的是,这似乎工作得不太好。 首先,我很难将内存初始化为整数值0
。 可以使用 memset() 来完成吗? 不过,我认为这不会影响我在尝试访问 pStatus[element]
时崩溃的原因。
我也不完全相信这种方法是最好的方法。 我真正想要的是一个反映布尔值状态的巨大位掩码。 我错过了什么吗?
I am trying to store a large amount of boolean information that is determined at run-time. I was wondering what the best method might be.
I have currently been trying to allocate the memory using:
pStatus = malloc((<number of data points>/8) + 1);
thinking that this will give me enough bits to work with. I could then reference each boolean value using the pointer in array notation:
pStatus[element]
Unfortunately this does not seem to be working very well. First, I am having difficulty initializing the memory to the integer value 0
. Can this be done using memset()
? Still, I don't think that is impacting why I crash when trying to access pStatus[element]
.
I am also not entirely convinced that this approach is the best one to be using. What I really want is essentially a giant bitmask that reflects the status of the boolean values. Have I missed something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
这确实为您的位分配了足够的字节。 然而,
这访问的是元素的第字节,而不是位。 因此,当元素超过总位数的八分之一时,您将访问分配的数组的末尾。
我会定义一些辅助函数
(为了清楚起见,对元素范围进行错误检查。您也可以制作这个宏)
This does allocate enough bytes for your bits. However,
This accesses the element'th byte, not bit. So when element is more than one-eighth of the total number of bits, you're accessing off the end of the array allocated.
I would define a few helper functions
(error checking on range of element left out for clarity. You could make this macros, too)
...认为这会给我足够的空间来工作。 然后,我可以使用数组表示法中的指针引用每个布尔值:
元素寻址字节,而不是位。 你想要类似的东西:
...thinking that this will give me enough bits to work with. I could then reference each boolean value using the pointer in array notation:
element is addressing bytes, not bits. You want something like:
小一点:要获得足够的内存来存储 N 位,(N/8) + 1 字节是不精确的(可能是太多)。
不过,(N+7)/8 始终是最小数。
Small point: to get enough memory to store N bits, (N/8) + 1 bytes is imprecise (can be one too many).
(N+7)/8 is always the minimum number, though.
嗯,最简单的答案是使用 calloc 而不是 malloc。
它被定义为将其分配的内存初始化为零,并且通常可以通过使用页面映射技巧来实现。
这将解决您的内存初始化问题。 这里的其他十几篇文章似乎充分解决了索引问题以及您偶尔分配额外字节的事实(哦,太恐怖了!),所以我不会在这里重复他们的内容。
Well, the simplest answer would be to use calloc instead of malloc.
It is defined to initialize the memory it allocates to zero, and can often do it by using page mapping tricks.
That will take care of your memory initialization problem. The other dozen posts here seem to adequately address the indexing problem and the fact that you occasionally allocate an extra byte (oh the horror!), so I won't repeat their content here.
pStatus[element] 将为您提供该地址处的整个字节。
要设置特定元素,您可以执行以下操作:
重置元素:
并测试元素:
初始分配应该是
您可以工作但偶尔会浪费一个字节的内容
pStatus[element] will give you an entire byte at that address.
To set a particular element you would do something like:
To reset an element:
and to test an element:
the initial allocation should be
what you had will work but wastes a byte occasionally
我不禁注意到,这里所有的 C 回复似乎都假设一个字节是 8 位。 这在 C 语言中不一定是正确的(尽管在大多数主流硬件上当然是正确的),因此在代码中做出这种假设是相当糟糕的形式。
编写与体系结构无关的代码的正确方法是,
然后在需要“
char
中的位数”的地方使用CHAR_BIT
宏。I can't help but notice that all replies in C here seem to assume that a byte is 8 bits. This is not necessarily true in C (although it will of course be true on most mainstream hardware), so making this assumption in code is rather bad form.
The proper way to write architecture-neutral code is to
and then use the
CHAR_BIT
macro wherever you need "the number of bits in achar
".让自己更快乐并定义一个类型和对该类型进行操作的函数。 这样,如果您发现位访问太慢,则可以将每个布尔值的内存单位更改为字节/字/长,或者如果内存确实是一个问题(即,如果您的集合大部分为零),则采用稀疏/动态数据结构,您可以只保留一个包含 1 坐标的列表。
您可以编写代码以完全不受位向量实现的更改的影响。
Make yourself happier and define a type and functions to operate on that type. That way if you discover that bit accesses are too slow, you can change the unit of memory per boolean to a byte/word/long or adopt sparse/dynamic data structures if memory is really an issue (ie, if your sets are mostly zeros, you could just keep a list with the coordinates of the 1's.
You can write your code to be completely immune to changes to the implementation of your bit vector.
pStatus[element] 不寻址该位。 它获得的确切字节取决于 pStatus 的类型 - 我假设 char* 或等效的 - 所以 pStatus[element] 为您提供第一个元素的字节。
你可以 memset 设置为 0,是的。
pStatus[element] does not address the bit. The exact byte it gets is dependent on the type of pStatus -- I assume char* or equivalent -- so pStatus[element] gets you the element'th byte.
You could memset to set to 0, yes.
那部分很好。
这就是你遇到麻烦的地方。 当你想要寻址位时,你就是寻址字节。
将为您提供数组中正确的字节。
That part's fine.
here's where you have trouble. You are address bytes, when you want to address bits.
will get you the right byte in the array.
您需要分配
c = malloc((N+7)/8)
字节,并且您可以使用clear with
设置第n个并使用test with
You need to allocate
c = malloc((N+7)/8)
bytes, and you can set the nth withclear with
and test with
如果你不介意必须编写包装器,你也可以使用 C++ 的 STL 中的 bit_set 或 bit_vector,看起来它们(尤其是后者)正是你所需要的,已经编码、测试和打包(以及大量的附加功能) )。
令人遗憾的是,我们缺乏在 C 应用程序中使用 C++ 代码的直接方法(不,创建包装器对我来说并不直接,也不有趣,而且从长远来看意味着需要更多工作)。
If you don't mind having to write wrappers, you could also use either bit_set or bit_vector from C++'s STL, seems like they (especially the latter) have exactly what you need, already coded, tested and packaged (and plenty of bells and whistles).
It's a real shame we lack a straight forward way to use C++ code in C applications (no, creating a wrapper isn't straight-forward to me, nor fun, and means more work in the long term).
std::vector
会出现什么问题?What would be wrong with
std::vector<bool>
?令我惊讶的是,这里只有一个答案提到了 CHAR_BIT。 一个字节通常是 8 位,但也不总是如此。
It amazes me that only one answer here mentions CHAR_BIT. A byte is often 8 bits, but not always.
您的分配代码是正确的,请参阅 这个答案来访问布尔值。
You allocation code is correct, see the
set_bit()
andget_bit()
functions given in this answer to access the boolean.如果您仅限于几个位,您可以代替 eaanon01 解决方案,还使用 bitfield 的 C 内置工具(很少有场合可以使用它们,但这就是一个)
对于这个位爆炸的东西,我可以推荐:
赫尼·沃伦斯《黑客之乐》
If you are limited to just a few bits you can instead of eaanon01 solution also use the c builtin facility of bitfield (there are very few occasion where you could use them, but this would be one)
For this bit banging stuff I can recommendate:
Herny Warrens "Hacker Delight"
在 C 语言中,布尔值“从来”不是一个单独的值。因此,结构体可能是为了让您继续下去。
确实,您没有初始化内存区域,因此您需要单独执行此操作。
这是一个简单的示例,说明如何使用联合结构和枚举来做到这一点
希望这会有所帮助。 此示例最多可以处理 64 个状态布尔值,并且可以轻松扩展。
此示例基于 Char = 8 位 int = 16 位 long int = 32 位和 long long int = 64 位
我现在还添加了对状态组的支持。
The boolean is "never" a separate value in C. So a struct might be in order to get you going.
It is true that you do not initialize the mem area so you need to do that individually.
Here is a simple example of how you could do it with unions structs and enums
Hope this helps. This example can handle up until 64 status booleans and could be easy extended.
This exapmle is based on Char = 8 bits int = 16 bits long int = 32 bits and long long int = 64 bits
I have now also added support for status groups.