Best way to handle endianness?

I’m building a library for MessagePack here: GitHub - Sinfaen/fortran-messagepack: Experimental library for messagepack support in fortran. (I am very new to Fortran btw)

MessagePack specifies big-endian for multi-byte data types, and I wrote this piece of code to detect the endianness of the host system at run-time:

logical function detect_little_endian()
    detect_little_endian = (1 == transfer([1_int8, 0_int8], 0_int16) )
end function

are there portability concerns with this? I’m assuming that the host system is only big or little endian here. I use the result of this procedure to control whether specific data types are byte-swapped when serializing or deserializing messagepack.

1 Like

I think the only problem might be when the int8 and int16 KIND values are unsupported by iso_fortran_env. Either one or both could be -1, for example.

An alternative might be to use int32 and int64 instead. A compiler is required to support a default kind and an extended precision kind of at least 18 decimal digits. Most compilers will map those two required KINDs to int32 and int64. So although the mapping is still arbitrary, there might be a better chance of things working this way.

On the other hand, if your code is packing one-byte, two-byte, and four-byte integers, then it probably requires int8 and int16 to be defined anyway. If a compiler doesn’t support the little endian detection expression you are using, it probably can’t be used for the rest of your program anyway, so your original expression is a good one to detect this along with the endianess.

The only minor comments I have about your expression is that it might be more consistent as

This compares directly the 16-bit values, rather than converting to 32-bits first.

The other comment is that this value might better be stored as a parameter in a shared module rather than as a run time expression. This would make this information available at compile time rather than later at run time, and that could be used, for example, to eliminate dead code by the compiler.

3 Likes

ah yeah, the spec does require me to handle 1, 2, 4 & 8 byte types. I think what I’ll do is add a check for those types not being defined so I can warn the user

Note in the C side of things, it’s more common to check for big-endianness like so:

const int i = 1;
#define is_bigendian() ( (∗(char∗)&i) == 0 )

Along the same lines, you may consider in Fortran:

logical, parameter :: IS_BIG_ENDIAN = iachar( c=transfer(source=1,mold="a") ) == 0

There are other ways of checking for the same, the above is just one option that can keep it consistent for you on the Fortran side.

2 Likes