snippetcMinor
Convert size_t to big endian on Linux
Viewed 0 times
convertendianbigsize_tlinux
Problem
I see that on Linux there are various built-in functions to convert endianness for specific integer width types, and they are probably faster than anything one can write and compile on their own. But I want to write a
Is this the fastest way?
size_t (under Linux in C), which does not have a specified width, to big-endian array of bytes, as fast as possible.Is this the fastest way?
#include
// write "from" to array of bytes "to" in big-endian fashion
void big_endian_size(unsigned char to[], size_t from) {
unsigned char *p = to + (sizeof(size_t) - 1);
while (1) {
*p = from;
if (to == p)
break;
p--;
from >>= CHAR_BIT;
}
}Solution
If you're looking for performance then you should, at least, provide a specialized version for the most common cases:
Specialized versions may simply reuse this:
Note that you may also simply return another
Also note that if you extract the 32 bit swap code into a separate function then you can use it both for 32 bit and 64 bit sizes (for example see byteswap.h for an implementation).
Do you need more? Assembly. For example on X86/X64 assembly you have
Notes: Why
void big_endian_size(uint8_t to[], size_t from) {
#if UINT32_MAX == SIZE_MAX
// Specialization for 4 bytes size_t
#elif UINT64_MAX == SIZE_MAX
// Same as above but for 8 bytes size_t
#else
// Your current implementation...
#endif
}Specialized versions may simply reuse this:
to[3] = from & 0x000000FF);
to[2] = (from & 0x0000FF00) >> 8;
// And so on...Note that you may also simply return another
size_t (instead of an array) with its bytes rotated. This will be considerably faster (also if implemented with a plain for to go through all bytes).Also note that if you extract the 32 bit swap code into a separate function then you can use it both for 32 bit and 64 bit sizes (for example see byteswap.h for an implementation).
Do you need more? Assembly. For example on X86/X64 assembly you have
BSWAP that does it in one instruction (I remember also ARM has but I don't remember the mnemonic), just check for target architecture to provide more and specialized versions. Notes: Why
&? Because truncation (let's imagine uint8_t val = 0xffffffff >> 8) is platform specific.Code Snippets
void big_endian_size(uint8_t to[], size_t from) {
#if UINT32_MAX == SIZE_MAX
// Specialization for 4 bytes size_t
#elif UINT64_MAX == SIZE_MAX
// Same as above but for 8 bytes size_t
#else
// Your current implementation...
#endif
}to[3] = from & 0x000000FF);
to[2] = (from & 0x0000FF00) >> 8;
// And so on...Context
StackExchange Code Review Q#162480, answer score: 4
Revisions (0)
No revisions yet.