Hacker News new | past | comments | ask | show | jobs | submit login

No, type punning via unions is a gcc extension.

The standard only allows reading a value as the type it was written with or as char, and an access as char is only good for copying. If a char access used different bit order, that would be OK according to the standard because you couldn't tell unless you violated the standard.

It seems every compiler will tolerate a memcpy for type punning, even though this isn't required.




C99 and C11 allow type punning via unions (although apparently that only gets mentioned in a footnote)

https://stackoverflow.com/questions/11639947/


Does this mean that memcpy() is really more of a language construct than a library function, since it cannot be implemented correctly in fully defined standard C?


Yes. Check here for a discussion: https://blog.regehr.org/archives/959


Everything defined in the standard is in principle a language construct: whether it is builtin in the compiler or an actual function is an implementation detail. For many compilers, memcpy is both: they have builtin handling for it but fall back to the library implementation when there is no optimization opportunities.

Having said that, it is possible to implement memcopy in standard C: char pointers have an explicit special exemption to the aliasing rule so you are allowed to inspect objects as array of chars.


memcpy is legal and fine. To borrow the example from above:

  double d = 3.14;
  uint64_t i;
  memcpy(&i, &d, sizeof(d));
is perfectly kosher.


> is perfectly kosher

Aren't exact-bitwidth integer types optional even with C99 (let alone preceding versions of standard)?


They are optional, but only in the sense that if you can't exactly represent e.g. uint64_t, there can't be a uint64_t type. So the example above is kosher in the sense that it's standards compliant, even if it isn't perfectly portable (for reasons unrelated to memset type punning; that you're using uint64_t in the first place).

If an implementation can't represent uint64_t exactly, it can still have a uint_least64_t type of whatever width works.


I certainly agree with what you said as you said it. However, as usual, it is the implementation that kills it.

a) I believe sizeof (double) * 8 == 64 is not enforced by the standard either. One could argue that it is hard to find anything else these days, but (for a contrived example) I believe nothing prevents you from making your own port of GCC for some purpose, and make 'double' be 'float'. (From my memories, it is even far enough from rocket science.)

b) It already happened to me personally, to work with code where people have implemented their own uintXX types (because of the lack of the standard ones), and then over time these became narrower/vider.

So if we would like to have it portable, I think, nothing beats:

union { double d; char cc [sizeof (double)]; };

and there we are, back to what is in the standard.


I mostly agree, but with b) IMO the problem was that you worked in an environment that was already not concerned with the standard. I'm not sure if it's OK by the standard for a user to define types named e.g. int32_t that don't comply to the standard restrictions.

sizeof (double) can be guaranteed to be 8 if __STDC_IEC_559__ is defined, so checking that is an additional hurdle if you want to use memcpy for punning. That said, I think it can be assumed that you're writing non-portable code for a specific set of platforms already if you are punning floats to integers, because the representation is implementation dependent in the first place. Probably you also know the environments in which it will be compiled as well, so the example is a bit contrived.

Very much agree that unions are the easiest and standard way to do type punning. There's so many misconceptions about this somehow being unclear in the standard. Sure, it does reflect poorly on the quality of the standard that Linux contributors don't understand it and that Linus Torvalds actively ignores it, but if you know what you're looking for it's often not that hard to find a definite answer.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: