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

5
根据这份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(转换为无符号字符))参数复制到s指向的对象的前n个字节中。” 这样做是更有效还是更明确? 这里是否涉及最佳实践?


5
在C语言中,'\0'是一个整型变量。不过,你使用什么类型并不重要。 - chris
2
我没有答案,但我必须说我也想过这个问题。个人而言,我会尽量明确。(我不知道将 0 转换为 '\0' 是否可能存在任何问题) - Xarn
2
@KasiyA,'\0' 不是 char 类型,它是一个 int 类型。 - chux - Reinstate Monica
3
只看了大约10秒钟,我发现这个问题有很多重复的:https://dev59.com/m2025IYBdhLWcg3wl3Am https://dev59.com/4XRA5IYBdhLWcg3w6SXZ https://dev59.com/PGQn5IYBdhLWcg3wGT8X - Elias Van Ootegem
1
确实很烦人!这个问题可能已经有答案,但它不是重复的。我没有问为什么要使用bzero而不是memset - 不是重复的。我没有问如何将char转换为int - 不是重复的。我没有问为什么memset需要一个int - 不是重复的。你对重复的定义太荒谬了。 - joemooney
显示剩余8条评论
2个回答

7
第二个参数是一个整数,为什么他们推荐使用'\0'而不是0呢?
为了明确,这个东西最终会变成一个NUL字符;毕竟,memset会将其转换为unsigned char。这只是一个风格问题,因为'\0'的类型是int,因此与0相同。

1
在C++中,任何符合规范的编译器,无论是正常的还是不正常的,在编译时都会将'\0'转换为0。在C语言中,没有发生转换,因为'\0'已经是int类型。 - Keith Thompson
在C语言中,字符字面量实际上是整数而不是字符。https://dev59.com/i3RC5IYBdhLWcg3wCMc6 - Steve Cox
该问题被标记为C和C++。在C中,'\0'的类型为int。在C++中,它的类型为char。(无论哪种情况,在memset的第二个参数中传递'\0'都是完全正确的。) - Keith Thompson

4

这种写法是否更加高效呢?

从某种意义上说是的:bzero 实际上从未成为标准库的一部分。这就是为什么你链接的页面建议使用 memset。因此,在可靠性方面,使用 memset 更加高效,可以确保你的代码在所有标准 C 编译器上都能编译。

'\0' 而非 0
标准要求字符可以安全地转换为 int:

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

因此,将 '\0' 传递给 int 参数并不是问题。更重要的是:你正在传递一个零转义序列,这实际上与传递 0 是相同的。
但是,这种写法更加明确: memset 将初始化 N 个字节为任何你传递的值。在 C 中,唯一保证只有一个字节大小的类型是 char 类型。

因此:

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

但是由于你正在设置12个字节,因此传递一个1字节大小的值更能反映这一点。出于这个原因,我更喜欢明确传递一个 char,但这取决于您。

memset 的历史:
函数 memset 已经存在了很长时间。事实上,它甚至存在于函数原型的早期。

还要记住的另一件事情是,在 C 语言中,字符常量本身就像大多数字面值一样是 int。


+1 表示完整回答;对于“它存在于函数原型的早期”的措辞不太清楚。 - chux - Reinstate Monica
\0 不是数字,所以你的引用不相关。 - Fred Foo
从某种意义上说,“bzero”实际上从未成为标准的一部分。 “从某种意义上说”是什么意思?“bzero”从未成为任何官方的C或C ++标准的一部分;这是明确无歧的。 - Keith Thompson
@KeithThompson:bzero已被POSIX标准化。 - Fred Foo
@KeithThompson 当然,除非原帖引用了POSIX :) - Fred Foo
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接