/*
(c) 2013 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=1077
*/
#include <stdio.h>
#include <stdint.h>
#define FS_PADDING_INSERT(name_, size_) uint8_t name_[size_];
#define FS_PADDING_SKIP(name_, size_)
#define FS_PACK_PUSH_1 __pragma(pack(push, 1))
#define FS_PACK_PUSH_4 __pragma(pack(push, 4))
#define FS_PACK_PUSH_8 __pragma(pack(push, 8))
#define FS_PACK_PUSH_SKIP
#define FS_PACK_POP __pragma(pack(pop))
#define FS_PACK_POP_SKIP
#define FS_DEFINE_POD(type_, declaration_) \
declaration_(type_, , FS_PADDING_INSERT, FS_PACK_PUSH_SKIP, FS_PACK_POP_SKIP); \
declaration_(type_, _PACK_0, FS_PADDING_SKIP, FS_PACK_PUSH_SKIP, FS_PACK_POP_SKIP); \
declaration_(type_, _PACK_1, FS_PADDING_INSERT, FS_PACK_PUSH_1, FS_PACK_POP); \
declaration_(type_, _PACK_4, FS_PADDING_INSERT, FS_PACK_PUSH_4, FS_PACK_POP); \
declaration_(type_, _PACK_8, FS_PADDING_INSERT, FS_PACK_PUSH_8, FS_PACK_POP); \
static_assert(sizeof(type_) == sizeof(type_##_PACK_0), "sizeof("#type_") != sizeof("#type_"_PACK_0)"); \
static_assert(sizeof(type_) == sizeof(type_##_PACK_1), "sizeof("#type_") != sizeof("#type_"_PACK_1)"); \
static_assert(sizeof(type_) == sizeof(type_##_PACK_4), "sizeof("#type_") != sizeof("#type_"_PACK_4)"); \
static_assert(sizeof(type_) == sizeof(type_##_PACK_8), "sizeof("#type_") != sizeof("#type_"_PACK_8)");
// struct Foo
#define FS_DECLARE_FOO(type_, tag_, padding_, pack_push_, pack_pop_) \
pack_push_ \
struct type_##tag_ \
{ \
uint8_t a; \
uint8_t b; \
uint8_t c; \
padding_(_reserved0, 1); \
uint32_t x; \
}; \
pack_pop_
FS_DEFINE_POD(Foo, FS_DECLARE_FOO);
#undef FS_DECLARE_FOO
// struct Bar
#define FS_DECLARE_BAR(type_, tag_, padding_, pack_push_, pack_pop_) \
pack_push_ \
struct type_##tag_ \
{ \
uint16_t num_foos; \
padding_(_reserved0, 2); \
Foo##tag_ foos[1]; \
}; \
pack_pop_
FS_DEFINE_POD(Bar, FS_DECLARE_BAR);
#undef FS_DECLARE_BAR
int main()
{
printf("*** Foo ***\n");
printf("Manual packing: %u bytes\n", sizeof(Foo));
printf("Default packing: %u bytes\n", sizeof(Foo_PACK_0));
printf("Tight packing: %u bytes\n", sizeof(Foo_PACK_1));
printf("32-bit packing: %u bytes\n", sizeof(Foo_PACK_4));
printf("64-bit packing: %u bytes\n", sizeof(Foo_PACK_8));
printf("\n*** Bar ***\n");
printf("Manual packing: %u bytes\n", sizeof(Bar));
printf("Default packing: %u bytes\n", sizeof(Bar_PACK_0));
printf("Tight packing: %u bytes\n", sizeof(Bar_PACK_1));
printf("32-bit packing: %u bytes\n", sizeof(Bar_PACK_4));
printf("64-bit packing: %u bytes\n", sizeof(Bar_PACK_8));
return 0;
}
// Compiled under Visual C++ 2012 (x64), output:
// *** Foo ***
// Manual packing: 8 bytes
// Default packing: 8 bytes
// Tight packing: 8 bytes
// 32-bit packing: 8 bytes
// 64-bit packing: 8 bytes
//
// *** Bar ***
// Manual packing: 12 bytes
// Default packing: 12 bytes
// Tight packing: 12 bytes
// 32-bit packing: 12 bytes
// 64-bit packing: 12 bytes