pragma pack vs. cplusplus align

TAlignedBytes definition is picked from ue4,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
typedef unsigned char uint8;
typedef int int32;
typedef unsigned int uint32;
 
template<int32 Size, uint32 Alignment>
struct TAlignedBytes; // this intentionally won't compile, we don't support the requested alignment
 
/** Unaligned storage. */
template<int32 Size>
struct TAlignedBytes<Size, 1>
{
	uint8 Pad[Size];
};
 
#define GCC_ALIGN(_align)
#define MS_ALIGN(n) __declspec(align(n))
 
// C++/CLI doesn't support alignment of native types in managed code, so we enforce that the element
// size is a multiple of the desired alignment
#ifdef __cplusplus_cli
#define IMPLEMENT_ALIGNED_STORAGE(Align) \
		template<int32 Size>        \
		struct TAlignedBytes<Size,Align> \
		{ \
			uint8 Pad[Size]; \
			static_assert(Size % Align == 0, "CLR interop types must not be aligned."); \
		};
#else
/** A macro that implements TAlignedBytes for a specific alignment. */
#define IMPLEMENT_ALIGNED_STORAGE(Align) \
	template<int32 Size>        \
	struct TAlignedBytes<Size,Align> \
	{ \
		struct MS_ALIGN(Align) TPadding \
		{ \
			uint8 Pad[Size]; \
		} GCC_ALIGN(Align); \
		TPadding Padding; \
	};
#endif
 
// Implement TAlignedBytes for these alignments.
IMPLEMENT_ALIGNED_STORAGE(16);
IMPLEMENT_ALIGNED_STORAGE(8);
IMPLEMENT_ALIGNED_STORAGE(4);
IMPLEMENT_ALIGNED_STORAGE(2);
 
#undef IMPLEMENT_ALIGNED_STORAGE

My test code is in vc2019 x64,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
struct TTask
{
	char ch2;
	char ch3;
	double d4;
	__int64 i64;
};
 
#pragma pack(push, 1)
struct TTaskB
{
	char ch2;
	alignas(16) char ch3;
	double d4;
	__int64 i64;
};
struct AAa
{
	char ch1;
	TAlignedBytes<sizeof(TTask), alignof(TTask)> TaskStorage;
};
struct AAb
{
	char ch1;
	TTask TaskStorage;
};
#pragma pack(pop)
 
void CMFCApplication1Dlg::OnBnClickedButton1()
{
	__int64 sizeTTask = alignof(TTask);			// sizeTTask is 8
	__int64 sizeTTaskB = alignof(TTaskB);			// sizeTTaskB is 16
 
	AAa aa;
	TTask& Task = *(TTask*)&aa.TaskStorage;
	__int64 gapAAa = (char*)&Task - (char*)&aa;		// gapAAa is 8
 
	AAb bb;
	TTask& TaskB = *(TTask*)&bb.TaskStorage;
	__int64 gapAAb = (char*)&TaskB - (char*)&bb;		// gapAAb is 1
}