为啥在 memset 中使用 '\0' 而不是 0?

Posted

技术标签:

【中文标题】为啥在 memset 中使用 \'\\0\' 而不是 0?【英文标题】:Why use '\0' instead of 0 for memset?为什么在 memset 中使用 '\0' 而不是 0? 【发布时间】:2014-05-22 14:59:27 【问题描述】:

根据这个 Unix 文档http://pubs.opengroup.org/onlinepubs/009695399/functions/bzero.html

The memset() function is preferred over bzero().

For maximum portability, it is recommended to replace 
the function call to bzero() as follows:

#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)

但是void *memset(void *s, int c, size_t n); 第二个参数是 int 那么为什么他们推荐 '\0' 而不是 0? memset() 文档说“memset() 函数应将 c (转换为无符号字符) arg 复制到第一个 s 指向的对象的 strong>n 个字节。"这是更有效还是更明确?这里是否涉及最佳实践?

【问题讨论】:

在 C 中,'\0' 是一个 int。但是,您使用哪个并不重要。 我没有答案,但我不得不说我也想知道这个。就我个人而言,我会尽量明确。 (我不知道转换 0 -> '\0' 可能出现任何问题) @KasiyA '\0' 不是char。这是一个int '\0'0 都是同一个常量。使用是一种风格选择。如果memset() 的目标是char *,IMO,'\0' 传达更多含义。否则使用0 Nips,只看了10秒左右,这个问题有大约一百万个骗子:***.com/questions/5919735/…***.com/questions/781668/char-to-int-conversion-in-c***.com/questions/17096990/why-use-bzero-over-memset 【参考方案1】:

第二个 arg 是一个 int 那么为什么他们推荐 '\0' 而不是 0?

为了清楚起见,这个东西最终会变成一个 NUL 字符;毕竟memset 会将其转换为unsigned char。这只是风格问题,因为'\0' 的类型为int,因此与0 相同。

【讨论】:

在 C++ 中,任何 符合 的编译器,无论是否正常,都会在编译时将 '\0' 转换为 0。在 C 中,不会发生转换,因为 '\0' 已经是 int 类型。 c 中的字符文字无论如何都是整数,而不是字符。 ***.com/questions/433895/… 该问题同时标记为 C 和 C++。在 C 中,'\0' 的类型为 int。在 C++ 中,它的类型为 char。 (无论哪种情况,将'\0' 作为memset 的第二个参数传递都是完全正确的。)【参考方案2】:

效率更高吗?

在某种程度上:bzero 从未真正成为标准的一部分。这就是为什么您链接到的页面建议使用memset。因此,使用memset 更有效,因为您可以放心,您的代码可以在所有标准 C 编译器上编译。

'\0' 而不是 0 该标准要求 char 可以安全地转换为 int:

基本源和基本执行字符集都应具有以下内容 成员: [...] 十进制数字0 1 2 3 4 5 6 7 8 9 [...] 在源和执行基本字符集中, 上述十进制数字列表中 0 之后的每个字符的值应大于 1 前一个的值。

所以将 '\0' 传递给 int 参数不是问题。更重要的是:您正在传递一个 zero-escape-sequence,这实际上与传递 0 相同。 然而,它更明确:memset 会将 N 个字节初始化为您传递给它的任何值。 C 中唯一保证为 1 且只有 1 个字节大的类型是 char 类型。

所以:

memset(some_ptr, 0, 12);
//is, in practice identical to:
memset(some_ptr, '\0', 12);

但是当您设置 12 个字节时,传递一个 1-byte-big 类型的值可以更好地反映这一点。出于这个原因,我更喜欢显式传递一个字符,但这取决于你。

memset 的历史:memset 功能已经存在很长时间了。事实上,它早在函数原型时代就已经存在了!

要记住的另一件事是,C 中的字符文字本身与大多数文字值一样,是整数。

【讨论】:

+1 以获得完整答案;不清楚“它早在函数原型时代就存在”的措辞。 \0 不是数字,因此您的报价无关紧要。 “在某种程度上:bzero 从来都不是标准的一部分。” “在某种程度上”是什么意思? bzero 从来不是任何官方 C 或 C++ 标准的一部分;这是明确的。 @KeithThompson: bzero 由 POSIX 标准化。 @larsmans:其实不是。 bzero 已被 POSIX.1-2001 弃用并标记为 LEGACY,并被 POSIX-1.2008 完全删除。您提出了一个很好的观点,它a 标准指定,但至少根据我的经验,“标准”一词通常指的是 ANSI 或 ISO 语言标准。

以上是关于为啥在 memset 中使用 '\0' 而不是 0?的主要内容,如果未能解决你的问题,请参考以下文章

为啥类的对象不可以用memset初始化,而结构体可以?

使用 memset 初始化整数数组而不是像 array[10]=0 这样的默认零初始化是不是有任何性能优势?

为啥 memset() 放在循环体内时不能正常工作?

关于memset()

在servicestack中使用protobuf,为啥order只能从1而不是0开始?

memset初始化指针指向