在一本C书中,我在一个实例中找到了实现动态调整大小数组的代码(简化):
void *contents = realloc(array->contents, array->max * sizeof(void *));
array->contents = contents;
memset(array->contents + old_max, 0, array->expand_rate + 1);
来源:Learn C The Hard Way – Chapter 34
我对memset
应该在这里实现的目标感到有些惊讶,但后来我才明白这是为了“#0;零”"重新分配的内存。
我用谷歌搜索,如果这是我在realloc
之后应该做的事情,并找到了关于此的stackoverflow答案:
可能无需执行
memset
[...]但是,即使你想把它归零所以一切都很好",或者真的需要新的指针
NULL
:C标准并不能保证所有-bits-zero是空指针常量(即NULL
),所以memset()
无论如何都不是正确的解决方案。
来源:How to zero out new memory after realloc
建议的解决方案而不是memset
然后使用for
循环来将内存设置为NULL
。
所以我的问题是,因为memset
并不一定意味着将值设置为NULL
并且for
循环解决方案似乎有点单调乏味 - 是否真的需要设置新分配的内存?
答案 0 :(得分:4)
所以我的问题是,因为memset并不一定意味着设置值 为NULL和for循环解决方案似乎有点乏味 - 是不是真的 需要设置新分配的内存吗?
realloc
没有初始化新分配的内存段的值。
因此,如果您计划读取该(未初始化的)内存的值,则需要初始化内存。因为从未初始化的内存中读取值将触发未定义的行为。
顺便说一下,使用realloc
(因为它可能失败)的安全方式是:
// Since using realloc with size of 0 is tricky and useless probably
// we use below check (from discussion with @chux)
if (new_size == 0)
dosmth();
else
{
new_p = realloc(p, new_size);
if (new_p == NULL)
{
// ...handle error
}else
{
p = new_p;
}
}
答案 1 :(得分:0)
将void *
设置为0是一个等于NULL
的值。可能memset(ptr, 0, size)
可以 - 但需要查看更多代码以确定。
OTOH:代码是否正确?也许应该是
// memset(array->contents + old_max, 0, array->expand_rate + 1);
memset(array->contents + old_max, 0, sizeof(void *) * (array->expand_rate + 1) );
答案 2 :(得分:0)
这是错误的:
但是,即使你想“把它归零所以一切都很好”,或者 真的需要新的指针为NULL:C标准没有 保证all-bits-zero为空指针常量(即 NULL),所以memset()无论如何都不是正确的解决方案。
C标准确实确实保证了这一点。
根据C standard的第6.3.2.3节:
值为0的整型常量表达式,或此类表达式 强制转换为
void *
类型,称为空指针常量。如果为null 指针常量被转换为指针类型,由此产生 指针,称为空指针,保证比较不等于 指向任何对象或函数的指针。将空指针转换为另一个指针类型会产生null 那种类型的指针。任何两个空指针都应该相等。
请注意,值为零的指针是 a 空指针。这并不意味着NULL
本身必须为零。但另请注意,“任何两个空指针应比较相等”。所以任何空指针都等于NULL
值。
由于memset()
将第二个参数作为整数值,因此将零整数值传递给memset()
将产生空指针。因为传递给memset()
的值是“[a] n整数常量表达式,值为0”,按照6.3.2.3。