On 2016-04-04 19:37, Peter Dimov wrote:
Andrey Semashev wrote:
void write_be32( uint_least32_t n, unsigned char p[4] ) { // I assume CHAR_BIT of 8 here
/* assert( n < 2^32 ); */
p[0] = ( n >> 24 ) & 0xFF; p[1] = ( n >> 16 ) & 0xFF; p[2] = ( n >> 8 ) & 0xFF; p[3] = n & 0xFF; }
For example, uint_least32_t could have non-base-2 representation, so as unsigned char, so the bit patterns that are stored to p would be also not base-2.
The representation of uint_least32_t doesn't matter. The expression n & 0xFF gives you a number between 0 and 255 that contains the lowest 8 VALUE bits of n, which is not the same as the STORAGE bits of n. In no possible representation would an uint_least32_t n with a value (m * 256 + 232) give you something other than 232 from (n & 0xFF).
With (n & 0xFF) you get a bit pattern which on the current architecture is interpreted as a number of 232. This bit pattern may be interpreted differently on another architecture. If you say that write_be32 is formally portable then it is imperative that the bit pattern it produces is interpreted equivalently on all architectures. To guarantee that, write_be32 might have do something else than what is written above or what we call byte swapping. Or otherwise you have to force the representation of input.
I agree that byte swapping is rarely the end goal. But in practice, with some restrictions, like assuming base-2 integers and 8-bit bytes across all systems you're planning to run your code on, endian conversions can serve as a means of data serialization.
And my point is that the interface you gave handles representational differences with the same ease as it handles differences that are limited to a byte swap.
It's actually the same for float. If your base is
void write_le32( float x, unsigned char p[4] );
the interface remains the same no matter what the representation of x. What matters is that you get a little-endian 32 bit IEEE float in p.
On a platform with non-IEEE floats, does write_le32 have to convert to IEEE format before producing the bits in p? What if the x value on the current platform is not representable in IEEE float?
If however you go for
float byteswap( float x );
then things get hairy even if restricted to IEEE, because an ordinary number may turn into a signaling NaN when byteswapped.
Absolutely agreed.