5

According to the this Unix documentation 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)


But void *memset(void *s, int c, size_t n); second arg is an int so why are they recommending '\0' instead of 0? The memset() doc says "The memset() function shall copy c (converted to an unsigned char) arg into each of the first n bytes of the object pointed to by s." Is this more efficient or simply more explicit? Is there a best practice involved here?

joemooney
  • 1,467
  • 1
  • 13
  • 17
  • 5
    In C, `'\0'` is an `int`. However, it shouldn't matter which you use. – chris May 22 '14 at 15:03
  • `bzero()` isn't standard, never use it – Iosif Murariu May 22 '14 at 15:03
  • 2
    I don't have an answer, but I have to say that I've wondered about this too. Personally I would go with trying to be explicit. (I am not aware of any possible problems with converting `0` -> `'\0'`) – Xarn May 22 '14 at 15:04
  • 2
    @KasiyA `'\0'` is not a `char`. It is an `int`. – chux - Reinstate Monica May 22 '14 at 15:04
  • @KasiyA : You're wrong. Character literals are ints. – Daniel Kamil Kozar May 22 '14 at 15:05
  • @DanielKamilKozar Assuming C, but this is also tagged C++... (on a side note, how did `char` literal end up being an `int` in C?) – Xarn May 22 '14 at 15:06
  • 1
    `'\0'` and `0` are both the same constant. Use is a style choice. If the target of `memset()` is a `char *`, IMO, `'\0'` conveys more meaning. Else use `0`. – chux - Reinstate Monica May 22 '14 at 15:07
  • @chux :: this is tagged `c++`; in C++, `'\0'` is not `int`, it's `char`. – Massa May 22 '14 at 15:09
  • @Massa. I said this to chux, Daniel Kamil Kozar but he said it's wrong.Please delete your wrong post that post for me. –  May 22 '14 at 15:11
  • @Massa Agree in C++ `'\0'` is `char` and in C it is `int`. Post is tagged both C & C++. – chux - Reinstate Monica May 22 '14 at 15:11
  • 3
    Nips, just looked around for like 10 seconds, this question has about a million dupes: http://stackoverflow.com/questions/5919735/why-does-memset-take-an-int-instead-of-a-char http://stackoverflow.com/questions/781668/char-to-int-conversion-in-c http://stackoverflow.com/questions/17096990/why-use-bzero-over-memset – Elias Van Ootegem May 22 '14 at 15:17
  • For those who have enough rep to see deleted answers, the constant `0` always has type `int`. Octal constants (yes, `0` is octal) can have any of several integer types depending on their values and the ranges of the predefined integer types. `0`, because of its value, can never be anything but `int`. – Keith Thompson May 22 '14 at 18:38
  • 1
    Nips indeed! The question may be answered but it is not a duplicate. I did not ask why use bzero over memset - not a dupe. I did not ask how to convert a char to an int - not a dupe. I did not ask why does memset take an int - not a dupe. Your definition of dupe is ludicrous. – joemooney May 23 '14 at 15:39

2 Answers2

7

second arg is an int so why are they recommending '\0' instead of 0?

To make it clear the thing is going to end up as a NUL character; after all memset will convert it to unsigned char. This is just a matter of style, because '\0' has type int and is thus the same as 0.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 1
    In C++, any *conforming* compiler, sane or otherwise, will convert `'\0'` to `0` at compile time. In C, no conversion occurs because `'\0'` is already of type `int`. – Keith Thompson May 22 '14 at 15:38
  • character literals in c are ints anyway, not chars. http://stackoverflow.com/questions/433895/why-are-c-character-literals-ints-instead-of-chars – Steve Cox May 22 '14 at 17:10
  • The question is tagged both C and C++. In C, `'\0'` has type `int`. In C++, it has type `char`. (In either case, passing `'\0'` as the second argument of `memset` is perfectly correct.) – Keith Thompson May 22 '14 at 18:36
4

Is it more efficient?

In a way: bzero was never actually part of the standard. That's why the page you link to recommends using memset. So using memset is more efficient in the sense that you can rest assured that your code compiles on all standard C compilers.

'\0' instead of 0
The standard requires that a char can be safely converted to an int:

Both the basic source and basic execution character sets shall have the following members:
[...]
the 10 decimal digits
0 1 2 3 4 5 6 7 8 9
[...]
In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.

So passing '\0' to an int param is not a problem. What's more: you are passing a zero-escape-sequence, which is actually the same as passing 0.
It is, however, more explicit: memset will initialize N bytes to whatever value you pass to it. The only type in C that is guaranteed to be 1 and only 1 byte big, is the char type.

So:

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

But seeing as you're setting 12 bytes, passing a value of a 1-byte-big type better reflects this. I prefer passing a char explicitly for that reason, but it's up to you.

History of memset:
The function memset has been around for ages. In fact, it existed back in the days the function prototypes!

Another thing to keep in mind is how character literals in C, by themselves, are, like most any literal value, ints.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • +1 for a complete answer; Unclear about wording in "it existed back in the days the function prototypes". – chux - Reinstate Monica May 22 '14 at 15:23
  • `\0` is not a digit, so your quote is irrelevant. – Fred Foo May 22 '14 at 15:30
  • "In a way: `bzero` was never actually part of the standard." What do you mean by "in a way"? `bzero` was never part of any official C or C++ standard; that's unambiguous. – Keith Thompson May 22 '14 at 15:39
  • @KeithThompson: `bzero` is standardized by POSIX. – Fred Foo May 22 '14 at 18:10
  • @larsmans: Actually, it isn't. `bzero` was deprecated and marked as LEGACY by POSIX.1-2001, and removed entirely by POSIX-1.2008. You make a good point that it *was* specified by *a* standard, but at least in my experience the phrase "the standard" usually refers to the ANSI or ISO language standard. – Keith Thompson May 22 '14 at 18:34
  • @KeithThompson Sure, except when the OP is citing POSIX :) – Fred Foo May 22 '14 at 21:33
  • @KeithThompson: I meant _"in a way"_ as in: `memset` is more efficient, because it's standard. Writing C code means writing portable code. `bzero` isn't standard, so your code won't be as portable, so for your code to be portable, it'd require you to define a `bzero` macro that expands to a `memset` call, which is silly, and makes your code less maintainable, hence: coding will be less efficient. But either way, I think I'll delete this answer later on – Elias Van Ootegem May 23 '14 at 06:36
  • I read it as "In a way," rather than "In a way:"; the colon vs. the comma I *thought* I saw there changes the meaning. Sorry for any confusion. – Keith Thompson May 23 '14 at 15:00