4

I recently ran into GCC's bug that prevents initializing some things with {0}. In that bug report, the person reporting it says:

The classic example in the C standard library is mbstate_t:

mbstate_t state = { 0 }; /* correctly zero-initialized */

versus the common but nonportable:

mbstate_t state;
memset(&state, 0, sizeof state);

While I prefer and try to use {0} to initialize something to zero, I have used, and have seen others use, the memset version to set something to zero. I haven't run into any portability issues in the past.

Question: Is using memset here really nonportable? If so, in what circumstances would it be nonportable?

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • iiuc, that bug doesn't *prevent* initializing struct's with `={0}`; it just presents an unnecessary warning which could be suppressed in all the usual ways. It's a bug, certainly, and it's marked as resolved (and only two years after the report :) ) – rici Jun 27 '14 at 03:28
  • @rici: Yeah, you're right. I build with `-Werror` so sometimes I forget what's normally an error and what's normally a warning. – Cornstalks Jun 27 '14 at 03:49

3 Answers3

8

Bitwise zero isn't guaranteed to be (T)0 for floating-point and pointer types. So if you memset one of those to zero, you're getting something that's at best implementation-defined.

This question lists a few machines where the null pointer wasn't bitwise zero.

I believe Cray made a few examples of machines where bitwise zero didn't make your floating-point number zero.

Community
  • 1
  • 1
tmyklebu
  • 13,915
  • 3
  • 28
  • 57
  • 3
    `memset` initialization works for "the types float and double, but only if the implementation has defined the macro __STDC_IEC_559__ to declare that it conforms to the IEC 60559 floating-point arithmetic annex" – YePhIcK Jun 26 '14 at 23:35
  • I don't really consider examples where `NULL` is not zero to be valid because the standard requires `NULL` to be "An integer constant expression with the value 0, or such an expression cast to type `void *`". – Cornstalks Jun 26 '14 at 23:37
  • 6
    @Cornstalks: You're misinterpreting the standard. The standard requires that the integral constant 0, when converted to a pointer type, to yield the null pointer. It does NOT require that the null pointer be represented by bitwise zero. See also http://c-faq.com/null/machnon0.html . – tmyklebu Jun 26 '14 at 23:41
  • @YePhIcK that macro may not be accurate, see my comment [here](http://stackoverflow.com/questions/19955968/why-is-math-pow0-0-1/19955996#comment29710753_19956041). – Shafik Yaghmour Jun 27 '14 at 01:27
1

"The use of memset for this purpose makes the assumption that a bit pattern of all zeros corresponds to a numeric value of zero or a pointer value of null. This is true for most types in most implementations of C, but is not a requirement of the ISO standard".

The above quote is taken from http://www.codepolice.org/c/memset.html (which was the first Google hit for "portability issues with memset")

YePhIcK
  • 5,816
  • 2
  • 27
  • 52
1

Is using memset here really nonportable?

It depends.

If so, in what circumstances would it be nonportable?

Setting an integer to zero bits using memset always makes the integer zero.
Setting a floating-point number to zero bits using memset usually makes number zero, but this is not guaranteed-- it depends on how floating point numbers are stored.
The story is same for pointers; a pointer whose bits are set to be zero isn't necessary a NULL pointer.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • Do you know, what the portable way for `mbstate_t` is? C11 p. 7.29.6 (3) „[…] A zero-valued `mbstate_t` object can be used to initiate conversion involving any multibyte character sequence, […]“. I'm not sure, what “zero-valued” means. [This](http://manpages.debian.org/cgi-bin/man.cgi?query=mbsinit&sektion=3&apropos=0&manpath=Debian+7.0+wheezy) says, `{0}` is the less portable way, but this is actually what I thought “zero-valued” means. – mafso Jun 27 '14 at 00:40