C语言 为什么在 memset 上使用 bzero?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17096990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:41:41  来源:igfitidea点击:

Why use bzero over memset?

cmemsetsystems-programming

提问by PseudoPsyche

In a Systems Programming class I took this previous semester, we had to implement a basic client/server in C. When initializing the structs, like sock_addr_in, or char buffers (that we used to send data back and forth between client and server) the professor instructed us to only use bzeroand not memsetto initialize them. He never explained why, and I'm curious if there is a valid reason for this?

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

I see here: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdownthat bzerois more efficient due to the fact that is only ever going to be zeroing memory, so it doesn't have to do any additional checking that memsetmay do. That still doesn't necessarily seem like a reason to absolutely not use memsetfor zeroing memory though.

我在这里看到:http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdownbzero是更有效的,由于一个只能将要归零记忆的事实,所以也没有必须做任何memset可能做的额外检查。不过,这似乎仍然不一定是绝对不memset用于清零内存的理由。

bzerois considered deprecated, and furthermore is a not a standard C function. According to the manual, memsetis preferred over bzerofor this reason. So why would you want to still use bzeroover memset? Just for the efficiency gains, or is it something more? Likewise, what are the benefits of memsetover bzerothat make it the de facto preferred option for newer programs?

bzero被认为已弃用,而且不是标准的 C 函数。根据手册,出于这个原因,memset优先于bzero。那么你为什么还要使用bzeroovermemset呢?只是为了提高效率,还是更多?同样,memsetover的好处是什么bzero使它成为新程序事实上的首选选项?

采纳答案by ouah

I don't see any reason to prefer bzeroover memset.

我看不出有任何理由喜欢bzeroover memset

memsetis a standard C function while bzerohas never been a C standard function. The rationale is probably because you can achieve exactly the same functionality using memsetfunction.

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

Now regarding efficiency, compilers like gccuse builtin implementations for memsetwhich switch to a particular implementation when a constant 0is detected. Same for glibcwhen builtins are disabled.

现在关于效率,编译器喜欢gcc使用内置实现,memset0检测到常量时会切换到特定实现。glibc禁用内置函数时相同。

回答by austin

I'm guessing you used (or your teacher was influenced by) UNIX Network Programmingby W. Richard Stevens. He uses bzerofrequently instead of memset, even in the most up-to-date edition. The book is so popular, I think it's become an idiom in network programming which is why you still see it used.

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

I would stick with memsetsimply because bzerois deprecated and reduces portability. I doubt you would see any real gains from using one over the other.

我会坚持使用,memset因为bzero它已被弃用并降低了可移植性。我怀疑你会看到使用一种而不是另一种的任何实际收益。

回答by Michael Burr

The one advantage that I think bzero()has over memset()for setting memory to zero is that there's a reduced chance of a mistake being made.

在一个优势,我认为bzero()有超过memset()设定存储到零的是,有一个错误的机会减少正在取得进展。

More than once I've come across a bug that looked like:

我不止一次遇到过这样的错误:

memset(someobject, size_of_object, 0);    // clear object

The compiler won't complain (though maybe cranking up some warning levels might on some compilers) and the effect will be that the memory isn't cleared. Because this doesn't trash the object - it just leaves it alone - there's a decent chance that the bug might not manifest into anything obvious.

编译器不会抱怨(尽管可能会在某些编译器上提高一些警告级别)并且结果将是内存没有被清除。因为这不会破坏对象——它只是让它独自存在——这个错误很可能不会表现成任何明显的东西。

The fact that bzero()isn't standard is a minor irritant. (FWIW, I wouldn't be surprised if most function calls in my programs are non-standard; in fact writing such functions is kind of my job).

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

In a comment to another answer here, Aaron Newton cited the following from Unix Network Programming, Volume 1, 3rd Edition by Stevens, et al., Section 1.2 (emphasis added):

在对此处另一个答案的评论中,Aaron Newton 从 Unix Network Programming, Volume 1, 3rd Edition by Stevens 等人的第 1.2 节中引用了以下内容(强调已添加):

bzerois not an ANSI C function. It is derived from early Berkely networking code. Nevertheless, we use it throughout the text, instead of the ANSI C memsetfunction, because bzerois easier to remember (with only two arguments) than memset(with three arguments). Almost every vendor that supports the sockets API also provides bzero, and if not, we provide a macro definition in our unp.hheader.

Indeed, the author of TCPv3 [TCP/IP Illustrated, Volume 3 - Stevens 1996] made the mistake of swapping the second and third arguments to memsetin 10 occurrences in the first printing. A C compiler cannot catch this error because both arguments are of the same type. (Actually, the second argument is an intand the third argument is size_t, which is typically an unsigned int, but the values specified, 0 and 16, respectively, are still acceptable for the other type of argument.) The call to memsetstill worked, because only a few of the socket functions actually require that the final 8 bytes of an Internet socket address structure be set to 0. Nevertheless, it was an error, and one that could be avoided by using bzero, because swapping the two arguments to bzerowill always be caught by the C compiler if function prototypes are used.

bzero不是 ANSI C 函数。它源自早期的 Berkely 网络代码。尽管如此,我们在整篇文章中都使用它,而不是 ANSI Cmemset函数,因为bzero(只有两个参数)比memset(三个参数)更容易记住。几乎每个支持套接字 API 的供应商也提供了bzero,如果没有,我们会在unp.h头文件中提供一个宏定义。

事实上,TCPv3 [TCP/IP Illustrated, Volume 3 - Stevens 1996] 的作者犯了一个错误,即memset在第一次印刷时将第二个和第三个参数交换为10 次。AC 编译器无法捕获此错误,因为两个参数的类型相同。(实际上,第二个参数是 an int,第三个参数是size_t,通常是 an unsigned int,但分别指定的值 0 和 16 对于其他类型的参数仍然是可以接受的。)调用memset仍然有效,因为只有一个很少有套接字函数实际上要求将 Internet 套接字地址结构的最后 8 个字节设置为 0。然而,这是一个错误,并且可以通过使用来避免 bzero,因为bzero如果使用函数原型,C 编译器将始终捕获到交换两个参数。

I also believe that the vast majority of calls to memset()are to zero memory, so why not use an API that is tailored to that use case?

我还相信绝大多数调用memset()都是零内存,那么为什么不使用针对该用例量身定制的 API?

A possible drawback to bzero()is that compilers might be more likely to optimize memcpy()because it's standard and so they might be written to recognize it. However, keep in mind that correct code is still better than incorrect code that's been optimized. In most cases, using bzero()will not cause a noticeable impact on your program's performance, and that bzero()can be a macro or inline function that expands to memcpy().

一个可能的缺点bzero()是编译器可能更有可能进行优化,memcpy()因为它是标准的,因此它们可能会被编写为识别它。但是,请记住,正确的代码仍然比经过优化的错误代码要好。在大多数情况下, usingbzero()不会对您的程序性能造成明显影响,并且bzero()可以是扩展为memcpy().

回答by paxdiablo

You probably shouldn'tuse bzero, it's not actually standard C, it was a POSIX thing.

您可能不应该使用bzero,它实际上不是标准 C,它是 POSIX 的东西。

And note that word "was" - it was deprecatedin POSIX.1-2001 and removedin POSIX.1-2008 in deference to memset so you're better off using the standard C function.

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

回答by gumchew

Wanted to mention something about bzero vs. memset argument. Install ltrace and then compare what it does under the hood. On Linux with libc6 (2.19-0ubuntu6.6), the calls made are exactly the same (via ltrace ./test123):

想提一些关于 bzero 与 memset 的争论。安装 ltrace,然后比较它在引擎盖下的作用。在带有 libc6 (2.19-0ubuntu6.6) 的 Linux 上,所做的调用完全相同(通过ltrace ./test123):

long m[] = {0}; // generates a call to memset(0x7fffefa28238, '
void *memset(void *s, int c, size_t n);
', 8) int* p; bzero(&p, 4); // generates a call to memset(0x7fffefa28230, '
void bzero(void *s, size_t n)
', 4)

I've been told that unless I am working in the deep bowels of libcor any number of kernel/syscall interface, I don't have to worry about them. All I should worry about is that the call satisfy the requirement of zero'ing the buffer. Others have mentioned about which one is preferable over the other so I'll stop here.

有人告诉我,除非我在libc或任何数量的内核/系统调用接口的深层工作,否则我不必担心它们。我应该担心的是调用满足将缓冲区归零的要求。其他人已经提到哪一个比另一个更可取,所以我会在这里停下来。

回答by havish

For memset function, the second argument is an intand the third argument is size_t,

对于 memset 函数,第二个参数是 an int,第三个参数是size_t

#ifndef bzero
#define bzero(d,n) memset((d),0,(n))
#endif

which is typically an unsigned int, but if the values like, 0 and 16for second and third argument respectively are entered in wrong order as 16 and 0 then, such a call to memset can still work, but will do nothing. Because the number of bytes to initialize are specified as 0.

这通常是 an unsigned int,但是如果0 and 16第二个和第三个参数的值分别以 16 和 0 的错误顺序输入,则对 memset 的这种调用仍然可以工作,但将无济于事。因为要初始化的字节数指定为0.

##代码##

Such an error can be avoided by using bzero, because swapping the two arguments to bzero will always be caught by the C compiler if function prototypes are used.

使用 bzero 可以避免这种错误,因为如果使用函数原型,将两个参数交换为 bzero 将始终被 C 编译器捕获。

回答by Tal Bar

In short:memsetrequire more assembly operations then bzero.

简而言之:memset需要更多的组装操作bzero

This is the source: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown

这是来源:http: //fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown

回答by Bruce

Have it any way you like. :-)

随心所欲。:-)

##代码##

Note that:

注意:

  1. The original bzeroreturns nothing, memsetreturns void pointer (d). This can be fixed by adding the typecast to void in the definition.
  2. #ifndef bzerodoes not prevent you from hiding the original function even if it exists. It tests the existence of a macro. This may cause lots of confusion.
  3. It's impossible to create a function pointer to a macro. When using bzerovia function pointers, this will not work.
  1. 原来bzero什么都不返回,memset返回空指针(d)。这可以通过在定义中添加类型转换为 void 来解决。
  2. #ifndef bzero即使它存在,也不会阻止您隐藏原始功能。它测试宏的存在。这可能会引起很多混乱。
  3. 创建指向宏的函数指针是不可能的。当bzero通过函数指针使用时,这将不起作用。

回答by Skynight

memset takes 3 parameters, bzero takes 2 in memory constrained that extra parameter would take 4 more bytes and most of the time itll be used to set everything to 0

memset 需要 3 个参数,bzero 在内存中需要 2 个参数,因为额外的参数需要多占用 4 个字节,而且大多数情况下它将用于将所有内容设置为 0