Is there a clever way of avoiding extra padding with nested classes in C++?
With #pragma pack(push, 1)
and some manual padding, you can get them to be the same.
#include <iostream>
int main() {
#pragma pack(push, 1)
struct align1 {
struct {
double d; // 8 bytes
bool b1; //+1 byte (+ 0 bytes padding) = 9 bytes
} subStruct;
bool b2; //+1 byte (+ 0 bytes padding) = 10 bytes
char pad_[6]; //+6 bytes (+ 0 bytes padding) = 16 bytes
};
#pragma pack(pop)
struct align2 {
double d; // 8 bytes
bool b1, b2; //+2 byte (+ 6 bytes padding) = 16 bytes
};
std::cout << "align1: " << sizeof(align1) << " bytes\n"; // 16 bytes
std::cout << "align2: " << sizeof(align2) << " bytes\n"; // 16 bytes
return 0;
}
Output:
align1: 16 bytes align2: 16 bytes
I explicitly rely on the permission to propose code which is "dirty or bad looking as" ... anything. To be even more clear, I only provide an idea. You need to test yourself and take responsibility yourself. I consider this question to explicitly allow untested code.
With this code:
typedef union
{
struct
{
double d; // 8 bytes
bool b1; //+1 byte (+ 7 bytes padding) = 16 bytes
} nested;
struct
{
double d; // 8 bytes
bool b1, b2; //+2 byte (+ 6 bytes padding) = 16 bytes
} packed;
} t_both;
I would expect the following attributes/features:
- contains the substruct as potentially typedefed elsewhere (can be used from an included header file)
- substruct accessable as
XXX.nested.d
andXXX.nested.b1
- at same address as
XXX.packed
- access to
XXX.packed.b2
to what is considered padding withinnested
- both substructs have the same total size, which I hope means that even making arrays of this is OK
Whatever you do with this, it probably conflicts with the requirement that when writing and reading a union, then all read accesses must be to the same part of the union as the most recent write. Writing one and reading the other would hence not be strictly allowed. That is what I consider unclearn about this code proposal. That said, I have often used this kind of unions in environments for which the respective construct has explicity been tested.
In order to illustrate here is a functionally identical and also equally unclean version, which better illustrates that the substruct can be typdefed elsewhere:
/* Inside an included header "whatever.h" : */
typedef struct
{
double d; // 8 bytes
bool b1; //+1 byte (+ 7 bytes padding) = 16 bytes
} t_ExternDefedStruct;
/* Content of including file */
#include "whatever.h"
typedef union
{
t_ExternDefedStruct nested;
struct
{
double d; // 8 bytes
bool b1, b2; //+2 byte (+ 6 bytes padding) = 16 bytes
} packed;
} t_both;