以通用方式安全地初始化 C 中的数组
我编写了一些代码,使用 memset 来初始化内置类型的数组,例如整数、短整型、浮点型,更重要的是指针,就像
typedef void* slot_t;
#define EMPTY_SLOT (slot_t)NULL
...
int n = 10;
slot_t slots[] = (slot_t[])malloc(sizeof(slot_t)*n)
memset(slots,(int)EMPTY_SLOT,n*sizeof(slot_t));
这段代码在 Linux32 中运行良好 一样memset
接受 32 位 int
作为第二个参数(即初始化元素),但对于 Linux64 来说并非如此,其中sizeof(slot_t)>sizeof(int)
,以及 IIRC,在其他平台中,memset
接受 char
作为其第二个参数。我尚未验证我在项目中遇到的任何错误是否是由于此造成的,但无论如何,可以肯定的是,最好采用更安全但仍然“通用”的方法(如果存在)。你知道吗?
I wrote some code that uses memset to initialize arrays of built-in types like ints, shorts, floats and, more importantly, pointers, like
typedef void* slot_t;
#define EMPTY_SLOT (slot_t)NULL
...
int n = 10;
slot_t slots[] = (slot_t[])malloc(sizeof(slot_t)*n)
memset(slots,(int)EMPTY_SLOT,n*sizeof(slot_t));
this code works nicely in Linux32 where memset
accepts 32-bit int
s as second argument (i.e. initializing element), but it's not so for Linux64, where sizeof(slot_t)>sizeof(int)
, and, IIRC, in other platforms where memset
accepts char
as its second argument. I have yet to verify that any of the bugs I'm experiencing in my project is due to this but, anyway, to be sure, it would be better to adopt a safer, but still "generic", method, if exists. Do you know any?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用它的干净内存
单独
Use
it's clean memory by itself
memset
用字节填充内存。请参阅此处。如果您想要一个通用解决方案 - 您应该编写一个可以迭代和填充的循环。如果你用 0 填充,那么它是什么类型的数据以及它的大小并不重要 - 只需用整个数组的
siezof
填充 0 (sizeof(slot_t) *n
)。由于您使用的是NULL
,它不必为 0(尽管通常是) - 我建议采用更安全的“循环”方法。memset
fills memory with bytes. See here.If you want a generic solution - you should write a loop that would iterate and fill. If you're filling with 0, then it doesn't matter what type of data it is and what size it has - just fill 0 with
siezof
of the whole array (sizeof(slot_t)*n
). Since you're usingNULL
, which doesn't have to be 0 (although usually is) - I suggest taking the safer "loop" approach.memset
实际上需要一个字符作为填充内存的值——请注意,它按字节填充。所以只需说0
。如果需要,您可以将其放入EMPTY_SLOT
宏中。或者,使用calloc()
。(此外,
malloc()
调用的返回类型应为slot_t *
。)memset
really wants a character as the value to fill the memory with -- note that it fills bytewise. So just say0
. You can put that in yourEMPTY_SLOT
macro if you want. Alternatively, usecalloc()
.(Also, the return type of your
malloc()
call should beslot_t *
.)memset()
的第二个参数是 int 类型,但它指定要存储在目标的每个字节中的值 - 这意味着,如果sizeof(int) == 4
,您将应有的内存归零四倍。对
slots
数组进行零填充的方法是(假设
slots
被正确声明为指针而不是数组),但空指针表示不是保证全位为零(可能是,但您不应该依赖它)。如果您想要完全的可移植性,则需要编写一个循环将每个元素设置为 NULL。
如果您愿意假设空指针全位为零,则可以使用 memset - 但请务必按照我指定的方式调用它。
The second argument to
memset()
is of type int, but it specifies a value to be stored in each byte of the destination -- which means that, ifsizeof(int) == 4
, you're zeroing four times as much memory as you should be.The way to zero-fill the
slots
array would be(assuming
slots
is correctly declared as a pointer rather than as an array), except that a null pointer representation isn't guaranteed to be all-bits-zero (it probably is, but you shouldn't depend on it).If you want complete portability, you'll need to write a loop to set each element to NULL.
If you're willing to assume that null pointers are all-bits-zero, you can use
memset
-- but be sure to call it as I specified.如果您想要一个完全通用的函数,它将对象数组设置为某个“模板”对象指定的值,您可以使用如下函数:
那么您的分配/初始化代码可能如下所示:
如果您想初始化一个指针数组,您可以使用另一个函数来更直接地处理这种情况:
我不确定我是否喜欢这两个函数对最后一个参数有细微不同的含义。如果我的程序需要这两种初始化,我可能也会坚持使用通用初始化指针数组。它的效率可能会低一些,但初始化通常不是瓶颈。
If you want a completely generic function that will set an array of objects to the values specified by some 'template' object, you could use a function like the following:
Then your allocation/initialization code might look like:
If you want to initialize an array of pointers, you could have another function that handled that case a little more directly:
I'm not sure I like that the two functions have a subtly different meaning for last parameter. If I had a need for both kinds of initialization in my program, I'd probably stick with using the generic one for initializing pointer arrays as well. It might be a bit less efficient, but initialization isn't usually a bottleneck.