C++ struct alignment question

后端 未结 6 820
清歌不尽
清歌不尽 2020-12-05 09:12

I have a predefined struct (actually several) where variables span across 32-bit word boundary. In Linux (and Windows using GCC) I am able to get my structs to pack to the

6条回答
  •  再見小時候
    2020-12-05 09:26

    Crazy idea: just write a C99 or C++03 -conforming program in the first place


    I would suggest not using vendor-specific C language extensions to match device or network bit formats. Even if you get the fields to line up using a series of one-per-vendor language extensions, you still have byte order to worry about, and you still have a struct layout that requires extra instructions to access.

    You can write a C99 conforming program that will work on any architecture or host and at maximum speed and cache efficiency by using the standardized C API string and memory copy functions and the Posix hton and ntoh functions.

    A good practice is to use the following functions for which there exist published standards:

    C99: memcpy(), Posix: htonl(), htons(), ntohl(), ntohs()
    

    Update: here is some code that should work the same everywhere. You may need to get from this project if Microsoft still hasn't implemented it for C99, or just make the usual assumptions about int sizes.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    struct packed_with_bit_fields {  // ONLY FOR COMPARISON
        unsigned int   a        : 3;
        unsigned int   b        : 1;
        unsigned int   c        : 15;
        unsigned int   troubleMaker : 16;
        unsigned short padding  : 13;
    } __attribute__((packed));       // USED ONLY TO COMPARE IMPLEMENTATIONS
    
    struct unpacked { // THIS IS THE EXAMPLE STRUCT
        uint32_t a;
        uint32_t b;
        uint32_t c;
        uint32_t troubleMaker;
    }; // NOTE NOT PACKED
    
    struct unpacked su;
    struct packed_with_bit_fields sp;
    char *bits = "Lorem ipsum dolor";
    
    int main(int ac, char **av) {
      uint32_t x;   // byte order issues ignored in both cases
    
      // This should work with any environment and compiler
      memcpy(&x, bits, 4);
      su.a = x & 7;
      su.b = x >> 3 & 1;
      su.c = x >> 4 & 0x7fff;
      memcpy(&x, bits + 2, 4);
      su.troubleMaker = x >> 3 & 0xffff;
    
      // This section works only with gcc
      memcpy(&sp, bits, 6);
      printf( sp.a == su.a
          &&  sp.b == su.b
          &&  sp.c == su.c
          &&  sp.troubleMaker == su.troubleMaker
          ? "conforming and gcc implementations match\n" : "huh?\n");
      return 0;
    }
    

提交回复
热议问题