49 lines
2.1 KiB
Plaintext
49 lines
2.1 KiB
Plaintext
Finally, one-line endianness detection in the C preprocessor
|
|
<p>In 30 years of C programming, I thought I’d seen everything. Well, every bizarre trick you could pull with the C preprocessor, anyway. I was <a href="http://stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine">wrong</a>. Contemplate this:</p>
|
|
<pre language="C">
|
|
#include <stdint .h>
|
|
|
|
#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
|
|
</pre>
|
|
<p>That is magnificently awful. Or awfully magnificent, I'm not sure which. And it pulls off a combination of qualities I've never seen before:</p>
|
|
<p><span id="more-5095"></span></p>
|
|
<ul>
|
|
<li>Actually portable (well, assuming you have C99 stdint.h, which is a pretty safe assumption in 2013).</li>
|
|
<li>Doesn't require runtime code.</li>
|
|
<li>Doesn't allocate storage, not even constant storage.</li>
|
|
<li>One line, no auxiliary definitions required.</li>
|
|
<li>Readily comprehensible by inspection.</li>
|
|
</ul>
|
|
<p>Every previous endianness detector I've seen failed one or more of these tests and annoyed me in so doing.</p>
|
|
<p>In GPSD it's replacing this mess:</p>
|
|
<pre language="C">
|
|
/*
|
|
__BIG_ENDIAN__ and __LITTLE_ENDIAN__ are define in some gcc versions
|
|
only, probably depending on the architecture. Try to use endian.h if
|
|
the gcc way fails - endian.h also doesn not seem to be available on all
|
|
platforms.
|
|
*/
|
|
#ifdef __BIG_ENDIAN__
|
|
#define WORDS_BIGENDIAN 1
|
|
#else /* __BIG_ENDIAN__ */
|
|
#ifdef __LITTLE_ENDIAN__
|
|
#undef WORDS_BIGENDIAN
|
|
#else
|
|
#ifdef BSD
|
|
#include <sys/endian.h>
|
|
#else
|
|
#include <endian.h>
|
|
#endif
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
#define WORDS_BIGENDIAN 1
|
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
#undef WORDS_BIGENDIAN
|
|
#else
|
|
#error "unable to determine endianess!"
|
|
#endif /* __BYTE_ORDER */
|
|
#endif /* __LITTLE_ENDIAN__ */
|
|
#endif /* __BIG_ENDIAN__ */
|
|
</pre>
|
|
<p>And that, my friends, is progress.</p>
|
|
<p>UPDATE: I was wrong: I thought the preprocessor would do all these operations, but it turns out this macro does expand to a small anount of code. It’s still pretty neat, though.</p>
|