1

我写了一些代码,使用memset来初始化内置类型的数组,如 int、shorts、float,更重要的是,指针,如

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

这段代码在memset接受 32 位ints 作为第二个参数(即初始化元素)的 Linux32 中运行良好,但对于 Linux64 则不是这样,其中sizeof(slot_t)>sizeof(int)和 IIRC 在memset接受char作为其第二个参数的其他平台上。我还没有验证我在项目中遇到的任何错误都是由于这个原因,但无论如何,可以肯定的是,如果存在的话,最好采用一种更安全但仍然“通用”的方法。你知道任何?

4

5 回答 5

2

利用

slot_t slots[] = (slot_t[])calloc(n,sizeof(slot_t))

它本身就是干净的记忆

于 2011-08-05T23:46:37.060 回答
1

memset真的想要一个字符作为填充内存的值——注意它是按字节填充。所以就说吧0。如果你愿意,你可以把它放在你的EMPTY_SLOT宏中。或者,使用calloc().

(另外,malloc()调用的返回类型应该是slot_t *。)

于 2011-08-05T23:44:19.957 回答
1

memset用字节填充内存。见这里

如果你想要一个通用的解决方案 - 你应该编写一个循环来迭代和填充。如果你用 0 填充,那么它是什么类型的数据以及它的大小都没有关系 - 只需用siezof整个数组 ( sizeof(slot_t)*n) 填充 0 即可。由于您使用的是NULL,它不一定是 0 (尽管通常是) - 我建议采用更安全的“循环”方法。

于 2011-08-05T23:47:18.817 回答
0

如果您想要一个完全通用的函数,它将对象数组设置为某个“模板”对象指定的值,您可以使用如下函数:

void init_array( void* arr, size_t nmemb, size_t size, void const* initializer)
{
    size_t i = 0;

    char* p = (char *) arr;

    for (i = 0; i < nmemb; ++i) {
        memcpy( p, initializer, size);
        p += size;
    }
}

然后您的分配/初始化代码可能如下所示:

typedef void* slot_t;

static const slot_t empty_slot = NULL;    // or make this a global if that 
                                          //  works better for your scenario

int n = 10;

// note: your original `malloc()` line:
//
//      slot_t slots[] = (slot_t[])malloc(sizeof(slot_t)*n)
//
// wouldn't work, as you can't assign to an array as a whole.
// That line shouldn't even compile.

slot_t* slots = (slot_t*)malloc(sizeof(slot_t)*n);

// completely generic initialization
init_array( slots, n, sizeof(slot_t), &empty_slot);

如果你想初始化一个指针数组,你可以有另一个函数更直接地处理这种情况:

void init_ptr_array( void* arr, size_t nmemb, void* initializer)
{
    size_t i = 0;
    void* p;

    for (; p < arr + nmemb; ++p) {
        *p = initializer;
    }
}

// arrays of object pointers
init_ptr_array( slots, n, empty_slot);

我不确定我是否喜欢这两个函数对最后一个参数的含义略有不同。如果我的程序中需要这两种初始化,我可能会坚持使用通用的初始化指针数组。它可能效率较低,但初始化通常不是瓶颈。

于 2011-08-06T23:59:05.630 回答
0

的第二个参数memset()是 int 类型,但它指定了要存储在目标的每个字节中的值——这意味着,如果sizeof(int) == 4,您将归零的内存是应有的四倍。

零填充slots数组的方法是

memset(slots, 0, n * sizeof *slots);

(假设slots正确地声明为指针而不是数组),除了不能保证空指针表示为全位为零(它可能是,但你不应该依赖它)。

如果您想要完全的可移植性,您需要编写一个循环来将每个元素设置为 NULL。

如果您愿意假设空指针全为零,您可以使用memset-- 但请务必按​​照我指定的方式调用它。

于 2011-08-05T23:46:19.453 回答