Is there a way to enforce specific endianness for a C or C++ struct?

前端 未结 11 1194
南方客
南方客 2020-12-13 09:24

I\'ve seen a few questions and answers regarding to the endianness of structs, but they were about detecting the endianness of a system, or converting data between the two d

相关标签:
11条回答
  • 2020-12-13 10:08

    No, I dont think so.

    Endianness is the attribute of processor that indicates whether integers are represented from left to right or right to left it is not an attribute of the compiler.

    The best you can do is write code which is independent of any byte order.

    0 讨论(0)
  • 2020-12-13 10:10

    Maybe not a direct answer, but having a read through this question can hopefully answer some of your concerns.

    0 讨论(0)
  • 2020-12-13 10:11

    A bit late to the party but with current GCC (tested on 6.2.1 where it works and 4.9.2 where it's not implemented) there is finally a way to declare that a struct should be kept in X-endian byte order.

    The following test program:

    #include <stdio.h>
    #include <stdint.h>
    
    struct __attribute__((packed, scalar_storage_order("big-endian"))) mystruct {
        uint16_t a;
        uint32_t b;
        uint64_t c;
    };
    
    
    int main(int argc, char** argv) {
        struct mystruct bar = {.a = 0xaabb, .b = 0xff0000aa, .c = 0xabcdefaabbccddee};
    
        FILE *f = fopen("out.bin", "wb");
        size_t written = fwrite(&bar, sizeof(struct mystruct), 1, f);
        fclose(f);
    }
    

    creates a file "out.bin" which you can inspect with a hex editor (e.g. hexdump -C out.bin). If the scalar_storage_order attribute is suppported it will contain the expected 0xaabbff0000aaabcdefaabbccddee in this order and without holes. Sadly this is of course very compiler specific.

    0 讨论(0)
  • 2020-12-13 10:13

    No, there's no such capability. If it existed that could cause compilers to have to generate excessive/inefficient code so C++ just doesn't support it.

    The usual C++ way to deal with serialization (which I assume is what you're trying to solve) this is to let the struct remain in memory in the exact layout desired and do the serialization in such a way that endianness is preserved upon deserialization.

    0 讨论(0)
  • 2020-12-13 10:14

    You could make the structure a class with getters and setters for the data members. The getters and setters are implemented with something like:

    int getSomeValue( void ) const {
    #if defined( BIG_ENDIAN )
        return _value;
    #else
        return convert_to_little_endian( _value );
    #endif
    }
    
    void setSomeValue( int newValue) {
    #if defined( BIG_ENDIAN )
        _value = newValue;
    #else
        _value = convert_to_big_endian( newValue );
    #endif
    }
    

    We do this sometimes when we read a structure in from a file - we read it into a struct and use this on both big-endian and little-endian machines to access the data properly.

    0 讨论(0)
提交回复
热议问题