-1

Is there a way to use macro for padding inside structs, I mean like that:

struct Monument{
    char name[32];
    PADDING( 4 * sizeof(int));
    int cityId;
    PADDING( 4 * sizeof(int));
    int age;

}

where PADDING(s) macro just adds space.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256

1 Answers1

1

You can define it like that:

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define PADDING(size) char TOKENPASTE2(padding_, __LINE__) [size]

Change field name prefix as you like it (preferably one that won't ever collide with other possible members).

Keep in mind (as mentioned by Remy Lebeau and François Andrieux in comments) that compiler can sometimes add unexpected padding. For reference you can read:

EDIT: Sorry, initial code was incorrect (it was incorrectly using __LINE__ expansion in macro). I fixed it using solution from: https://stackoverflow.com/a/1597129/1561140

Marcin Sucharski
  • 1,191
  • 9
  • 9
  • 1
    Also be sure to set the structure alignment to 1 byte so the compiler doesn't add its own padding between members. – Remy Lebeau Nov 29 '17 at 21:18
  • @FrançoisAndrieux My mistake, thanks! I've fixed it. – Marcin Sucharski Nov 29 '17 at 21:34
  • 2
    I would recommend a mention that c++ sometimes adds unexpected padding. For example, due to alignment restrictions, `PADDING(1);` between two `int` would actually introduce more than 1 byte of padding on most implementations. There's also hard to tell sometimes what the compiler might do to [non-standard layouts](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout). See [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member). – François Andrieux Nov 29 '17 at 21:38
  • I'll use the pack method since I do not know if gcc pads by 8 on 64bit, but the struct I define always respect the 4 bytes pattern. Could you explain how the # and ##works? – Marco Spampinato Nov 30 '17 at 22:17
  • `##` merges two arguments on text-level (so padding_ ## 20 became padding_20 in resulting code). Additional levels of macros (TOKENPASTE and TOKENPASTE2) are needed because of the way the macros work (padding_ ## __LINE__ would be expanded to padding__LINE__ otherwise). For details read this answer: https://stackoverflow.com/a/1597129/1561140 – Marcin Sucharski Dec 01 '17 at 17:08