#include <iostream>
#include <stdint.h>

#pragma pack(push, 1)

/* struct from OpenEXR; should be packed with the pragma directive  */
typedef struct
{
    uint32_t x_size;
    uint32_t y_size;
    uint8_t  level_and_round;
} exr_attr_tiledesc_t;

/* same struct but reordered */
typedef struct
{
    uint8_t  level_and_round;
    uint32_t x_size;
    uint32_t y_size;
} new1_exr_attr_tiledesc_t;

/* same as first struct but with packed forced */
typedef struct
{
    uint32_t x_size;
    uint32_t y_size;
    uint8_t  level_and_round;
} __attribute__((packed, aligned(1))) new2_exr_attr_tiledesc_t;

#pragma pack(pop)

int main() {
    std::cout << sizeof(exr_attr_tiledesc_t) << " "
              << sizeof(new1_exr_attr_tiledesc_t) << " "
              << sizeof(new2_exr_attr_tiledesc_t) << "\n";

    return 0;
}


On Mac OS X Leopart (10.5),
    `g++-mp-7 main.cxx && ./a.out` gives: 12 9 9
    `g++ main.cxx && ./a.out`      gives: 9  9 9
    `g++-mp-7 main.cxx && ./a.out` gives: 9  9 9

    `g++* -arch ppc64 && ./a.out`  gives: 9 9 9

OpenEXR requires this struct to be packed, so 9 is the correct result.
It not clear what effects there would be in reordering, so force packed with __attribute__.

--- src/lib/OpenEXRCore/openexr_attr.h.orig	2023-03-28 08:25:15.000000000 -0700
+++ src/lib/OpenEXRCore/openexr_attr.h	2023-05-13 06:48:03.000000000 -0700
@@ -274,7 +274,7 @@
     uint32_t x_size;
     uint32_t y_size;
     uint8_t  level_and_round;
-} exr_attr_tiledesc_t;
+} __attribute__((packed, aligned(1))) exr_attr_tiledesc_t;
 
 /** @brief Macro to access type of tiling from packed structure. */
 #define EXR_GET_TILE_LEVEL_MODE(tiledesc)                                      \
