Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么在memset上使用bzero?_C_Memset_Systems Programming - Fatal编程技术网

C 为什么在memset上使用bzero?

C 为什么在memset上使用bzero?,c,memset,systems-programming,C,Memset,Systems Programming,在上学期我参加的一个系统编程课程中,我们必须用C语言实现一个基本的客户机/服务器。当初始化结构时,比如中的sock\u addr\u或char缓冲区(我们用来在客户机和服务器之间来回发送数据)教授指示我们只使用bzero而不使用memset来初始化它们。他从未解释过原因,我很好奇这是否有正当的理由 我在这里看到:bzero效率更高,因为它只会对内存进行归零,所以它不需要像memset那样做任何额外的检查。不过,这仍然不一定是绝对不使用memset对内存进行调零的理由 bzero被认为是不推荐使用

在上学期我参加的一个系统编程课程中,我们必须用C语言实现一个基本的客户机/服务器。当初始化结构时,比如中的
sock\u addr\u或char缓冲区(我们用来在客户机和服务器之间来回发送数据)教授指示我们只使用
bzero
而不使用
memset
来初始化它们。他从未解释过原因,我很好奇这是否有正当的理由

我在这里看到:
bzero
效率更高,因为它只会对内存进行归零,所以它不需要像
memset
那样做任何额外的检查。不过,这仍然不一定是绝对不使用
memset
对内存进行调零的理由

bzero
被认为是不推荐使用的,而且它不是标准的C函数。根据手册,出于这个原因,
memset
优于
bzero
。那么,您为什么还要在
memset
上使用
bzero
?只是为了提高效率,还是更多?同样地,
memset
bzero
有什么好处,使其成为较新程序事实上的首选选项?

我猜您使用了W.Richard Stevens的UNIX网络编程(或者您的老师受到了影响)。他经常使用
bzero
而不是
memset
,即使是在最新版本中。这本书很受欢迎,我认为它已经成为网络编程中的一个习惯用语,这就是为什么你仍然看到它被使用的原因


我会坚持使用
memset
,因为
bzero
不受欢迎,降低了可移植性。我怀疑你会看到使用一个比另一个有什么实际好处。

我看不出有任何理由更喜欢
bzero
而不是
memset

memset
是标准的C函数,而
bzero
从来都不是C标准函数。基本原理可能是因为您可以使用
memset
函数实现完全相同的功能


现在,关于效率,像
gcc
这样的编译器使用
memset
的内置实现,当检测到常量
0
时,这些实现会切换到特定的实现。当内置被禁用时,
glibc
也是如此。

我认为
bzero()
memset()
设置内存为零有一个优点,那就是减少了出错的机会

我不止一次遇到这样一个bug:

memset(someobject, size_of_object, 0);    // clear object
编译器不会抱怨(尽管可能会在某些编译器上启动一些警告级别),结果是内存没有被清除。因为这不会破坏对象——只会让它单独存在——所以很有可能bug不会表现为任何明显的东西

bzero()
不是标准的事实是一个轻微的刺激。(FWIW,如果我的程序中的大多数函数调用都是非标准的,我不会感到惊讶;事实上,编写这样的函数是我的工作)

在对另一个答案的评论中,Aaron Newton引用了Stevens等人出版的《Unix网络编程》第1卷第3版第1.2节(重点添加)中的以下内容:

bzero
不是ANSI C函数。它起源于早期的伯克利 网络代码。然而,我们在全文中使用它 因为
bzero
更容易记住 (只有两个参数)而不是
memset
(有三个参数)。几乎 每个支持sockets API的供应商还提供
bzero
,以及 如果没有,我们将在
unp.h
标题中提供宏定义

事实上,TCPv3[TCP/IP插图,第3卷-Stevens 1996]的作者犯了一个错误,即交换了第二个 和
memset
的第三个参数,在第一个变量中出现10次 打印
。C编译器无法捕获此错误,因为这两个参数 是同一类型的。(实际上,第二个参数是
int
和 第三个参数是
size\u t
,它通常是一个
无符号int
, 但分别指定的值0和16仍然可以接受 对
memset
的调用仍然有效, 因为实际上只有少数套接字函数需要 Internet套接字地址结构的最后8个字节必须设置为0。 然而,这是一个错误,可以通过使用
bzero
,因为将两个参数交换到
bzero
将始终是 如果使用函数原型,C编译器会捕获

我还认为,对
memset()
的绝大多数调用都是对零内存的调用,所以为什么不使用针对该用例定制的API呢

bzero()
的一个可能的缺点是编译器可能更倾向于优化
memcpy()
,因为它是标准的,所以编写它们可能是为了识别它。但是,请记住,正确的代码仍然比经过优化的错误代码要好。在大多数情况下,使用
bzero()
不会对程序的性能造成明显的影响,而且
bzero()
可以是一个宏或内联函数,可以扩展到
memcpy()
,您可能不应该使用
bzero
,它实际上不是标准的C,而是POSIX


请注意单词“was”-它在POSIX.1-2001中被弃用,在POSIX.1-2008中被删除,以尊重memset,因此您最好使用标准C函数。

对于memset函数,第二个参数是
int
,第三个参数是
size\u t

void *memset(void *s, int c, size_t n);
这通常是一个
无符号int
,但是如果第二个和第三个参数的值分别为,
0和16
void bzero(void *s, size_t n)
#ifndef bzero
#define bzero(d,n) memset((d),0,(n))
#endif
long m[] = {0}; // generates a call to memset(0x7fffefa28238, '\0', 8)
int* p;
bzero(&p, 4);   // generates a call to memset(0x7fffefa28230, '\0', 4)