Endianness

bitproto’s wire format is little-endian on every platform: the lowest byte index on the wire holds the least-significant bits of a field. This is a fixed property of the encoding, independent of the machine that runs the encoder or decoder — two peers with different byte orders always interoperate.

Language support

Whether the host CPU is big-endian only ever mattered for C, because only C reads an integer field’s raw memory bytes. Python and Go operate on integer values with shifts and masks, which is byte-order independent by construction.

Target

How bits are moved

Big-endian host

Python

value math on Python ints

always correct

Go

value shifts on typed fields

always correct

C (standard mode)

lib/c runtime

correct

C (optimization mode)

generated bit-copy statements

correct

So nothing special is required for Go or Python. The remainder of this page is about C.

C standard mode

The C library (lib/c/bitproto.c) detects a big-endian host automatically (via __BYTE_ORDER__ for GCC/Clang, __ARM_BIG_ENDIAN for ACLE-compatible Arm toolchains such as TI Arm Clang, __big_endian__ for legacy TI ARM CGT, __BIG_ENDIAN__ for other toolchains, and __LITTLE_ENDIAN__ == 0 for IAR) and selects an endian-neutral code path. You may also force it by defining BP_BIG_ENDIAN when compiling the library, for toolchains that expose none of these macros:

$ cc -DBP_BIG_ENDIAN -c bitproto.c

On a little-endian host the library is byte-for-byte unchanged, so there is no performance impact on the common target.

C optimization mode

Optimization mode generates plain bit-copy statements that read and write integer fields through their in-memory bytes. To stay correct on both little-endian and big-endian hosts, by default bitproto emits two equivalent code paths guarded by a preprocessor macro:

#ifndef BP_BIG_ENDIAN
    // fast byte-pointer path (little-endian hosts)
#else
    // portable bit-shift path (big-endian hosts)
#endif

A big-endian host is auto-detected (via __BYTE_ORDER__ for GCC/Clang, __ARM_BIG_ENDIAN for ACLE-compatible Arm toolchains such as TI Arm Clang, __big_endian__ for legacy TI ARM CGT, __BIG_ENDIAN__ for other toolchains, and __LITTLE_ENDIAN__ == 0 for IAR); you may also force the big-endian path by defining BP_BIG_ENDIAN when compiling the generated code. The little-endian path is identical to earlier bitproto releases, so there is no performance change on little-endian targets — only the generated source is a little larger.

The --endian option

If you know your target’s byte order you can drop the unused path and shrink the generated source with the --endian option (optimization mode only):

# default: both paths, host auto-detected
$ bitproto c example.bitproto -O

# only the fast little-endian path (smaller output, no big-endian support)
$ bitproto c example.bitproto -O --endian=little

# only the portable big-endian path
$ bitproto c example.bitproto -O --endian=big

--endian only affects optimization-mode C/C++ code. It has no effect on the wire format, and none on Go or Python.