如果大小为0,可以使用空指针调用memset()吗?

时间:2011-12-21 22:06:57

标签: c malloc memset

由于某种原因,我想手动滚动malloc()的归零版本。为了最大限度地减少算法的复杂性,我想写一下:

void * my_calloc(size_t size)
{
    return memset(malloc(size), 0, size);
}

size == 0时这个定义明确吗?可以使用零大小调用malloc(),但这允许它返回空指针。随后的memset调用是否正常,或者这是未定义的行为,我需要添加一个条件if (size)

我非常想避免多余的条件检查!

假设malloc()没有失败。实际上,那里也会有一个malloc()的手动版本,它将在失败时终止。

像这样:

void * my_malloc(size_t size)
{
    void * const p = malloc(size);
    if (p || 0 == size) return p;
    terminate();
}

3 个答案:

答案 0 :(得分:9)

这是glibc声明:

extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));

__nonnull表明它希望指针为非空。

答案 1 :(得分:6)

修改重新:

  

我后来添加了这个:假设malloc()永远不会失败。问题是只有大小可以是0

我明白了。因此,如果指针为NULL 大小为0,则只希望事物安全。

参考POSIX文档

,没有指定使用NULL指针调用memset应该是安全的(如果你用零计数或大小调用它...那就更有趣了' ,但也没有指定)。

在“信息”部分甚至没有提及它。

请注意,第一个链接提及

  

此参考页面上描述的功能与ISO C标准一致。此处描述的要求与ISO C标准之间的任何冲突都是无意的。 IEEE Std 1003.1-2001的这一卷遵循ISO C标准

更新我可以确认ISO C99标准(n1256.pdf)与POSIX文档同样简短 C ++ 11规范只是引用了ansi memset和朋友的C标准。

答案 2 :(得分:4)

以下是C99标准对此的说法:

7.1.4“库函数的使用

  

如果函数的参数具有无效值(例如函数域外的值,或程序地址空间外的指针,或空指针,或指向不可修改存储的指针)相应的参数不是const限定的)或具有可变数量参数的函数不期望的类型(提升后),行为是未定义的。

7.21.1“字符串函数约定”(请记住memset()位于string.h

  

如果声明为size_t n的参数指定了函数数组的长度,则在调用该函数时,n的值可以为零。除非在本子条款中对特定函数的描述中另有明确说明,否则此类调用上的指针参数仍应具有有效值,如7.1.4中所述。

7.21.6.1“memset函数”

  

memset函数将c的值(转换为unsigned char)复制到s指向的对象的前n个字符中。

严格来说,由于标准指定s必须指向一个对象,因此传入空指针将是UB。添加支票(与malloc()相比的成本将会非常小)。另一方面,如果你知道malloc()不能失败(因为你有一个终止的自定义),那么显然你不需要在调用memset()之前进行检查。