11

How can I disable structure padding in C without using pragma?

Justin
  • 84,773
  • 49
  • 224
  • 367
Manu
  • 5,534
  • 6
  • 32
  • 42
  • This is non-standard. Whether (and if so how) this is possible depends entirely on which implementation of C you're using. – Matthew Flaschen Nov 29 '10 at 07:47
  • I think there is no other way to do this. – frast Nov 29 '10 at 07:48
  • There may be a compiler-specific compiler command-line option. – ChrisW Nov 29 '10 at 07:52
  • 6
    "Close as not a real question"? Seriously? Some people seem to have a rather bizarre idea as to what constitutes a real question IMNSHO :-/ Perhaps they think the OP is being difficult and should just use `#pragma`. But, guess what? Individual pragmas are _not_ part of the standard(other than the STDC ones). It may be that OP is using a compiler that _has_ no `#pragma pack` and they're porting code from a platform that does. – paxdiablo Nov 29 '10 at 08:26
  • @pax, several people (including you) have noted that the question can't be fully answered without knowing the compiler. I think that's exactly what "cannot be reasonably answered in its current form" means. I encourage @Manu to add this information. – Matthew Flaschen Nov 29 '10 at 09:10
  • 1
    @Matthew Flaschen: "you can't do it in standard C" seems like a reasonable full answer to the question. – JeremyP Nov 29 '10 at 12:05
  • @JeremyP - So? How does that make this not a real question? If you believe that is the answer then post it thusly and ... Tada! You now have a question with an answer! (directly contradicting "cannot be answered") Magic! – Justin Nov 30 '10 at 03:05
  • @Kragen, I think you should read the exchanges again :-) I'm pretty certain the you and Jeremy actually _agree_ with each other here. – paxdiablo Nov 30 '10 at 04:24
  • @Kragen: yep. I'm on your side! – JeremyP Nov 30 '10 at 09:13
  • @Kragen: and the reason I didn't post my answer is because somebody else (several somebody elses actually) had already posted it :) – JeremyP Nov 30 '10 at 09:14
  • @JeremyP, yeah I think I should have probably @ed my comment at @Matthew. – Justin Dec 01 '10 at 01:29

6 Answers6

17

There is no standard way of doing this. The standard states that padding may be done at the discretion of the implementation. From C99 6.7.2.1 Structure and union specifiers, paragraph 12:

Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type.

Having said that, there's a couple of things you can try.


The first you've already discounted, using #pragma to try and convince the compiler not to pack. In any case, this is not portable. Nor are any other implementation-specific ways but you should check into them as it may be necessary to do it if you really need this capability.


The second is to order your fields in largest to smallest order such as all the long long types followed by the long ones, then all the int, short and finally char types. This will usually work since it's most often the larger types that have the more stringent alignment requirements. Again, not portable.


Thirdly, you can define your types as char arrays and cast the addresses to ensure there's no padding. But keep in mind that some architectures will slow down if the variables aren't aligned properly and still others will fail miserably (such as raising a BUS error and terminating your process, for example).

That last one bears some further explanation. Say you have a structure with the fields in the following order:

char C; // one byte
int  I; // two bytes
long L; // four bytes

With padding, you may end up with the following bytes:

CxxxIIxxLLLL

where x is the padding.

However, if you define your structure as:

typedef struct { char c[7]; } myType;
myType n;

you get:

CCCCCCC

You can then do something like:

int *pInt = &(n.c[1]);
int *pLng = &(n.c[3]);
int myInt = *pInt;
int myLong = *pLng;

to give you:

CIILLLL

Again, unfortunately, not portable.


All these "solutions" rely on you having intimate knowledge of your compiler and the underlying data types.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    Note, on some systems accessing misaligned addresses (`int *pLng = &(n.c[3]);int myLong = *pLng;`) will fail at all (e. g. 68000 and ARM will fail). So padding is required there. – Vovanium Nov 29 '10 at 10:29
  • Agreed, @Vovanium, hence my "fail miserably" comment. – paxdiablo Nov 30 '10 at 04:25
3

Other than compiler options like pragma pack, you cannot, padding is in the C Standard.

You can always attempt to reduce padding by declaring the smallest types last in the structure as in:

struct _foo {
     int a;  /* No padding between a & b */
     short b;
} foo;

struct _bar {
     short b; /* 2 bytes of padding between a & b */
     int a;
} bar;

Note for implementations which have 4 byte boundaries

SiegeX
  • 135,741
  • 24
  • 144
  • 154
1

On some architectures, the CPU itself will object if asked to work on misaligned data. To work around this, the compiler could generate multiple aligned read or write instructions, shift and split or merge the various bits. You could reasonably expect it to be 5 or 10 times slower than aligned data handling. But, the Standard doesn't require compilers to be prepared to do that... given the performance cost, it's just not in enough demand. The compilers that support explicit control over padding provide their own pragmas precisely because pragmas are reserved for non-Standard functionality.

If you must work with unpadded data, consider writing your own access routines. You might want to experimenting with types that require less alignment (e.g. use char/int8_t), but it's still possible that e.g. the size of structs will be rounded up to multiples of 4, which would frustrate packing structures tightly, in which case you'll need to implement your own access for the entire memory region.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
0

If you really want structs without padding: Define replacement datatypes for short, int, long, etc., using structs or classes that are composed only of 8 bit bytes. Then compose your higher level structs using the replacement datatypes.

C++'s operator overloading is very convenient, but you could achieve the same effect in C using structs instead of classes. The below cast and assignment implementations assume the CPU can handle misaligned 32bit integers, but other implementations could accommodate stricter CPUs.

Here is sample code:

#include <stdint.h>
#include <stdio.h>

class packable_int { public:

  int8_t b[4];

  operator int32_t () const       { return *(int32_t*) b; }
  void operator =  ( int32_t n )  { *(int32_t*) b = n; }

};

struct SA {
  int8_t   c;
  int32_t  n;
} sa;

struct SB {
  int8_t        c;
  packable_int  n;
} sb;

int main () {
  printf ( "sizeof sa  %d\n", sizeof sa );    // sizeof sa  8               
  printf ( "sizeof sb  %d\n", sizeof sb );    // sizeof sb  5               
  return 0;
}
mpb
  • 1,277
  • 15
  • 18
0

Either you let compiler do padding, or tell it not to do using #pragma, either you just use some bunch of bytes like a char array, and you build all your data by yourself (shifting and adding bytes). This is really inefficient but you'll exactly control the layout of the bytes. I did that sometimes preparing network packets by hand, but in most case it's a bad idea, even if it's standard.

kriss
  • 23,497
  • 17
  • 97
  • 116
0

We can disable structure padding in c program using any one of the following methods.

-> use __attribute__((packed)) behind definition of structure. for eg.

struct node {
    char x;
    short y;
    int z;
} __attribute__((packed));

-> use -fpack-struct flag while compiling c code. for eg.

$ gcc -fpack-struct -o tmp tmp.c

Hope this helps. Thanks.