We recently found some code submitted to our codebase, along the following lines:
#pragma pack(push,1)
struct xyzzy {
BITMAPINFOHEADER header;
char plugh;
long twisty;
} myVar;
My question is: does the packing apply only to the immediate structure or might it affect the packing of the BITMAPINFOHEADER as well. I can't see the latter case being very useful since it would make the structure different to what you would get from the Windows API calls, for example. Case in point, let's assume the structure is:
typedef struct {
char aChar;
DWORD biSize;
} BITMAPINFOHEADER;
That structure would be vastly different with a packing of one rather than the default eight for Windows (32-bit anyway, may be sixteen for 64-bit).
Is the BITMAPINFOHEADER "protected" from the packing by virtue of the fact it's almost certainly be declared earlier? If it was declared as part of the outer declaration, would it be subject to the packing then?
From the relevant documentation:
pack takes effect at the first struct, union, or class declaration after the pragma is seen. pack has no effect on definitions.
header is a member definition, so it isn't affected.
it was declared as part of the outer declaration, would it be subject to the packing then?
Yes, as it would be a struct declaration.
Also, as Lightness Races in Orbit remarks in a comment, a more convincing wording can be found immediately before:
To pack a class is to place its members directly after each other in memory.
i.e. it says nothing about what those members themselves contain, which may be data and/or padding. The fact that (as explored above) packedness is attached to a type would seem to reinforce that
Still, the documentation is vague enough, so it's best to test that this interpretation is correct; both gcc and VC++ behave as expected. Not that I'm particularly surprised - anything different would break havoc in the type system (taking a pointer to a member of a packed structure would actually provide a pointer to something different than its type says1).
The general idea is: once you finish defining a struct, its binary layout is fixed, and any of its instantiations will conform to it, including subobjects of packed structures. The current #pragma pack value is considered only when defining new structures, and when doing so the binary layout of the members is a fixed black box.
Notes
To be honest, this is a bit of an x86-centric view; machines with stronger alignment requirements would object that even pointers to layout-correct but misaligned structures aren't kosher: although the offsets of fields relative to the given pointer are correct, they aren't really pointers that can be used as they are.
OTOH, given a pointer to an unaligned object you can always detect that it's unaligned and memcpy it to a correctly-aligned location, so it's not as bad as a hypothetical pointer to a packed object, whose layout is effectively unknown unless you happen to know the packing of its parent.
From what I have seen, it only applies to immediate structure.
Take a look at the snippet below:
#include <stdio.h>
struct /*__attribute__((__packed__))*/ struct_Inner {
char a;
int b;
char c;
};
struct __attribute__((__packed__)) struct_Outer {
char a;
int b;
char c;
struct struct_Inner stInner;
};
int main()
{
struct struct_Inner oInner;
struct struct_Outer oOuter;
printf("\n%zu Bytes", sizeof(oInner));
printf("\n%zu Bytes", sizeof(oOuter));
}
Prints:
12 Bytes
18 Bytes
When I pack the struct_Inner it prints:
6 Bytes
12 Bytes
This is when using GCC 7.2.0.
Again, this is not specific to C standard by any means (I just had to read), its more to do with what compilers do.
Is the BITMAPINFOHEADER "protected" from the packing by virtue of the fact it's almost certainly be declared earlier?
I guess yes. It would entirely depend upon the way BITMAPINFOHEADER is declared.
Assuming GCC (or Clang emulating GCC), you can find some relevant information at Structure Layout Pragmas, where it says that the presence of the push preserves the current packing state on a stack of states:
For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives that change the maximum alignment of members of structures (other than zero-width bit-fields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.
#pragma pack(n) simply sets the new alignment.
#pragma pack() sets the alignment to the one that was in effect when compilation started (see also command-line option -fpack-struct[=n] see Code Gen Options).
#pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.
#pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).
Thus, the #pragma in the code added affects all subsequent structure definitions too, until countermanded by #pragma pack(pop). I'd be worried about that.
The documentation doesn't say what happens if you do #pragma pack(pop) when there is no state on the internal stack. Most likely, it falls back to the setting when compilation started.
According to GCC reference:
In the following example struct my_packed_struct's members are
packed closely together, but the internal layout of its s member is
not packed - to do that, struct my_unpacked_struct would need to
be packed too.
struct my_unpacked_struct
{
char c;
int i;
};
struct my_packed_struct __attribute__ ((__packed__))
{
char c;
int i;
struct my_unpacked_struct s;
};
You may only specify this attribute on the definition of a enum, struct or union, not on a typedef which does not also define the
enumerated type, structure or union.
This does not directly answer the question, but might offer an idea why existing compilers decided not to pack sub-structs, and why future compilers are unlikely to change that.
A packing that transitively affected sub-structures would break the type system in subtle ways.
Consider:
//Header A.h
typedef struct {
char aChar;
DWORD biSize;
} BITMAPINFOHEADER;
// File A.c
#include <A.h>
void doStuffToHeader(BITMAPINFOHEADER* h)
{
// compute stuff based on data stored in h
// ...
}
// File B.c
#include <A.h>
#pragma pack(push,1)
struct xyzzy {
BITMAPINFOHEADER header;
char plugh;
long twisty;
} myVar;
void foo()
{
doStuffToHeader(&myVar.header);
}
I pass a pointer to a packed struct to a function that is not aware of the packing. Any attempts by the function to read or write data from the struct will easily break in horrible ways. If a compiler deems this unacceptable, it has two possibilities for fixing the problem:
Transparently unpack the sub-struct into a temporary for the function call and re-pack the result later.
Internally change the type of the header field in xyzzy to something that indicates that it's now a packed type and incompatible with normal BITMAPINFOHEADER.
Both of these are obviously problematic. With this reasoning, even if I wanted to write a compiler that supported packing of sub-structs, I would run into numerous follow-up problems. I'd expect my users to start questioning my design decisions in this regard very soon.
Related
I've got some code provided by a vendor that I'm using and its typedef'ing an enum with __attribute__((aligned(1), packed)) and GCC is complaining about the multiple attributes:
error: ignoring attribute 'packed' because it conflicts with attribute 'aligned' [-Werror=attributes]
Not sure what the best approach is here. I feel like both of these attributes are not necessary. Would aligned(1) not also make it packed? And is this even necessary for an enum? Wouldn't it be best to have the struct that this enum goes into be packed?
Thanks!
I've removed the packed attribute and that works to make GCC happy but I want to make sure that it will still behave the same. This is going into an embedded system that relies on memory mapped registers so I need the mappings to be correct or else things won't work.
Here's an example from the code supplied by the vendor:
#define DMESCC_PACKED __attribute__ ((__packed__))
#define DMESCC_ENUM8 __attribute__ ((aligned (1), packed))
typedef enum DMESCC_ENUM8 {DMESCC_OFF, DMESCC_ON} dmescc_bittype_t;
typedef volatile struct {
dmescc_bittype_t rx_char_avail : 1;
dmescc_bittype_t zero_count : 1;
dmescc_bittype_t tx_buf_empty : 1;
dmescc_bittype_t dcd : 1;
dmescc_bittype_t sync_hunt : 1;
dmescc_bittype_t cts : 1;
dmescc_bittype_t txunderrun_eom : 1;
dmescc_bittype_t break_abort : 1;
} DMESCC_PACKED dmescc_rr0_t;
When I build the above code I get the GCC error I mentioned above.
Documentation here: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes emphasis mine:
When used on a struct, or struct member, the aligned attribute can only increase the alignment; in order to decrease it, the packed attribute must be specified as well. When used as part of a typedef, the aligned attribute can both increase and decrease alignment, and specifying the packed attribute generates a warning.
Note that the effectiveness of aligned attributes for static variables may be limited by inherent limitations in the system linker and/or object file format. On some systems, the linker is only able to arrange for variables to be aligned up to a certain maximum alignment. (For some linkers, the maximum supported alignment may be very very small.) If your linker is only able to align variables up to a maximum of 8-byte alignment, then specifying aligned(16) in an __attribute__ still only provides you with 8-byte alignment. See your linker documentation for further information.
Older GNU documentation said something else. Also, I don't know what the documentation is trying to say here: "specifying the packed attribute generates a warning", because there is no warning in case I do this (gcc x86_64 12.2.0 -Wall -Wextra):
typedef struct
{
char ch;
int i;
} __attribute__((aligned(1), packed)) aligned_packed_t;
However, this effectively places the struct on a 5 byte offset, where the first address appears to be 8 byte aligned (which might be a thing of the linker as suggested in the above docs). We'd have to place it in an array to learn more.
Since I don't really don't trust the GNU documentation, I did some trial & error to reveal how these work in practice. I created 4 structs:
one with aligned(1)
one with such a struct as its member and also aligned(1) in itself
one with packed
one with both aligned(1) and packed (again this compiles cleanly no warnings)
For each struct I created an array, then printed the address of the first 2 array items. Example:
#include <stdio.h>
typedef struct
{
char ch;
int i;
} __attribute__((aligned(1))) aligned_t;
typedef struct
{
char ch;
aligned_t aligned_member;
} __attribute__((aligned(1))) struct_aligned_t;
typedef struct
{
char ch;
int i;
} __attribute__((packed)) packed_t;
typedef struct
{
char ch;
int i;
} __attribute__((aligned(1),packed)) aligned_packed_t;
#define TEST(type,arr) \
printf("%-16s Address: %p Size: %zu\n", #type, (void*)&arr[0], sizeof(type)); \
printf("%-16s Address: %p Size: %zu\n", #type, (void*)&arr[1], sizeof(type));
int main (void)
{
aligned_t arr1 [3];
struct_aligned_t arr2 [3];
packed_t arr3 [3];
aligned_packed_t arr4 [3];
TEST(aligned_t, arr1);
TEST(struct_aligned_t, arr2);
printf(" Address of member: %p\n", arr2[0].aligned_member);
TEST(packed_t, arr3);
TEST(aligned_packed_t, arr4);
}
Output on x86 Linux:
aligned_t Address: 0x7ffc6f3efb90 Size: 8
aligned_t Address: 0x7ffc6f3efb98 Size: 8
struct_aligned_t Address: 0x7ffc6f3efbb0 Size: 12
struct_aligned_t Address: 0x7ffc6f3efbbc Size: 12
Address of member: 0x40123000007fd8
packed_t Address: 0x7ffc6f3efb72 Size: 5
packed_t Address: 0x7ffc6f3efb77 Size: 5
aligned_packed_t Address: 0x7ffc6f3efb81 Size: 5
aligned_packed_t Address: 0x7ffc6f3efb86 Size: 5
The first struct with just aligned(1) didn't make any difference against a normal struct.
The second struct where the first struct was included as a member, to see if it would be misaligned internally, did not pack it any tighter either, nor did the member get allocated at a misaligned (1 byte) address.
The third struct with only packed did get allocated at a potentially misaligned address and packed into 5 bytes.
The fourth struct with both aligned(1) and packed works just as the one that had packed only.
So my conclusion is that "the aligned attribute can only increase the alignment" is correct and as expected aligned(1) is therefore nonsense. However, you can use it to increase the alignment. ((aligned(16), packed) did give 16 bit size, which effectively cancels packed.
Also I can't make sense of this part of the manual:
When used as part of a typedef, the aligned attribute can both increase and decrease alignment, and specifying the packed attribute generates a warning.
Either I'm missing something or the docs are wrong (again)...
Not sure what the best approach is here. I feel like both of these
attributes are not necessary. Would aligned(1) not also make it
packed?
No, it wouldn't. From the docs:
The aligned attribute specifies a minimum alignment (in bytes) for
variables of the specified type.
and
When attached to an enum definition, the packed attribute indicates that the smallest integral type should be used.
These properties are related but neither is redundant with the other (which makes GCC's diagnostic surprising).
And is this even necessary for an enum? Wouldn't it be best to
have the struct that this enum goes into be packed?
It is meaningful for an enum to be packed regardless of how it is used to compose other types. In particular, having packed on an enum is (only) about the storage size of objects of the enum type. It does not imply packing of structure types that have members of the enum type, but you might want that, too.
On the other hand, the alignment requirement of the enum type is irrelevant to the layout of structure types that have the packed attribute. That's pretty much the point of structure packing.
I've removed the packed attribute and that works to make GCC happy but
I want to make sure that it will still behave the same. This is going
into an embedded system that relies on memory mapped registers so I
need the mappings to be correct or else things won't work.
If only one of the two attributes can be retained, then packed should be that one. Removing it very likely does cause meaningful changes, especially if the enum is used as a structure member or as the type of a memory-mapped register. I can't guarantee that removing the aligned attribute won't also cause behavioral changes, but that's less likely.
It might be worth your while to ask the vendor what version of GCC they use for development and testing, and what range of versions they claim their code is compatible with.
Overall, however, the whole thing has bad code smell. Where it is essential to control storage size exactly, explicit-size integer types such as uint8_t should be used.
Addendum
With regard to the example code added to the question: that the enum type in question is used as the type of a bitfield changes the complexity of the question. Portable code steers well clear of bitfields.
The C language specification does not guarantee that an enum type such as that one can be used as the type of a bitfield member, so you're straight away into implementation-defined territory. Not that using one of the types the specification designates are supported would delay that very long, because many of the properties of bitfields and the structures containing them are implementation defined anyway, in particular,
which data types other than qualified and unqualified versions of _Bool, signed int, and unsigned int are allowed as the type of a bitfield member;
the size and alignment requirement of the addressible storage units in which bitfields are stored (the spec does not connect these in any way with bitfields' declared types);
whether bitfields assigned to the same addressible storage unit are arranged from least-significant position to most, or the opposite;
whether bitfields can be split across adjacent addressible storage units;
whether bitfield members may have atomic type.
GCC's definitions for these behaviors are here: https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html#Structures-unions-enumerations-and-bit-fields-implementation. Note well that many of them depend on the target ABI.
To use the vendor code safely, you really need to know which compiler it was developed for and tested against, and if that's a version of GCC, what target ABI. If you learn or are willing to assume GCC targeting the same ABI that you are targeting, then keep packed, dump aligned(1), and test thoroughly. Otherwise, you'll probably want to do more research.
For code that is compiled on various/unknown architectures/compilers (8/16/32/64-bit) a global mempool array has to be defined:
uint8_t mempool[SIZE];
This mempool is used to store objects of different structure types e.g.:
typedef struct Meta_t {
uint16_t size;
struct Meta_t *next;
//and more
}
Since structure objects always have to be aligned to the largest possible boundary e.g. 64-byte it has to be ensured that padding bytes are added between those structure objects inside the mempool:
struct Meta_t* obj = (struct Meta_t*) mempool[123] + padding;
Meaning if a structure object would start on a not aligned address, the access to this would cause an alignment trap.
This works already well in my code. But I'm still searching for a portable way for aligning the mempool start address as well. Because without that, padding bytes have to be inserted already between the array start address and the address of the first structure inside the mempool.
The only way I have discovered so far is by defining the mempool inside a union together with another variable that will be aligned by the compiler anyways, but this is supposed be not portable.
Unfortunately for embedded platforms my code is also compiled with ANSI C90 compilers. In fact I cannot make any guess what compilers are exactly used. Because of this I'm searching for an absolutely portable solution and I guess any kind of preprocessor directives or compiler specific attributes or language features that were added after C90 cannot be used
You can use _Alignas, which is part of the C11 standard, to force a particular alignment.
_Alignas(uint64_t) uint8_t mempool[SIZE];
(struct Meta_t*) mempool will lead to undefined behavior for more reasons than alignment - it's also a strict aliasing violation.
The best solution might be to create a union such as this:
typedef union
{
struct Meta_t my_struct;
uint8_t bytes[sizeof(struct Meta_t)];
} thing;
This solves both the alignment and the pointer aliasing problems and works in C90.
Now if we do *(thing)mempool then this is well-defined since this (lvalue) access is done through a union type that includes an uint8_t array among its members. And type punning between union members is also well-defined in C. (No solution exists in C++.)
Unfortunately, this ...
This mempool is used to store objects of different structure types
... combined with this ...
I'm searching for an absolute portable solution and I guess any kind of preprocessor directives or compiler specific attributes or language features that were added after C90 cannot be used
... puts you absolutely up a creek, unless you know in advance all the structure types with which your memory pool may be used. Even the approach you are taking now does not conform strictly to C90, because there is no strictly-conforming way to determine the alignment of an address, so as to compute how much padding is needed.* (You have probably assumed that you can convert it to an integer and look at the least-significant bits, but C does not guarantee that you can determine anything about alignment that way.)
In practice, there is a variety of things that will work in a very wide range of target environments, despite not strictly conforming to the C language specification. Interpreting the result of converting a pointer to an integer as a machine address, so that it is sensible to use it for alignment computations, is one of those. For appropriately aligning a declared array, so would this be:
#define MAX(x,y) (((x) < (y)) ? (y) : (x))
union max_align {
struct d { long l; } l;
struct l { double d; } d;
struct p { void *p; } p;
unsigned char bytes[MAX(MAX(sizeof(struct d), sizeof(struct l)), sizeof(struct p))];
};
#undef MAX
#define MEMPOOL_BLOCK_SIZE sizeof(union max_align)
union maxalign mempool[(size + MEMPOOL_BLOCK_SIZE - 1) / MEMPOOL_BLOCK_SIZE];
For a very large set of C implementations, that not only ensures that the pool itself is properly aligned for any use by strictly-conforming C90 clients, but it also conveniently divides the pool into aligned blocks on which your allocator can draw. Refer also to #Lundin's answer for how pointers into that pool would need to be used to avoid strict aliasing violations.
(If you do happen to know all the types for which you must ensure alignment, then put one of each of those into union max_align instead of d, l, and p, and also make your life easier by having the allocator hand out pointers to union max_align instead of pointers to void or unsigned char.)
Overall, you need to choose a different objective than absolute portability. There is no such thing. Avoiding compiler extensions and language features added in C99 and later is a great start. Minimizing the assumptions you make about implementation behavior is important. And where that's not feasible, choose the most portable option you can come up with, and document it.
*Not to mention that you are relying on uint8_t, which is not in C90, and which is not necessarily provided even by all C99 and later implementations.
i have a struct which represents a set of hardware registers. Here, some parts are reserved and must neither be written nor read. Is there a placeholder or something similar instead of using an obvious variable naming?
typedef volatile struct RegisterStruct
{
uint8 BDH;
uint8 BDL;
...
uint8 IR;
uint8 RESERVED0; // this area should not be accessed
...
}
Obvious naming would be the right thing to use, as there's no "reserved" feature in C.
You can use arrays of byte-sized integers to correctly pad to the right length:
typedef volatile struct RegisterStruct
{
uint8_t BDH;
uint8_t BDL;
uint8_t IR;
uint8_t __RESERVED[num_of_reserved_bytes]; // this area should not be accessed
uint8_t NEXT_REGISTER_NAME;
};
The problem with using structs for register mapping in general (or similarly, for data communication protocol mapping), is that a struct may contain padding bytes anywhere.
If you use a struct (or union) for such purposes, you have to ensure that padding is disabled, by adding a line like for example
_Static_assert(sizeof(RegisterStruct) == sizeof(uint8_t)*4, "Padding detected");
This will prevent padding bugs, as it will block structs with padding from compiling.
Unfortunately, you cannot disable struct padding in a portable manner; most of the time you don't want to disable it because it will make the programs slower at best, in the worst case you'll get hardware exceptions for misaligned access, all depending on CPU.
The most common non-standard extension to disable padding is #pragma pack(1), but it is non-standard and non-portable.
In my opinion, the best way to avoid all such problems is to avoid structs entirely for the actual mapping. Instead, just declare everything as plain volatile variables. (Or by using macros, which is unfortunately the only way you can map something to a specific memory location in standard C).
And when you have gotten that far, there's no need to use any "reserved" place holders. Simply don't map anything to those reserved memory locations.
There's actually really no sound reason why you would want to have a number of hardware registers in a struct, even though it is for some reason mighty popular to do so among embedded compilers. You'll find that register maps written for such compilers are unreadable and also extremely non-standard.
For communication protocols it makes more sense to have structs, but then you would typically write serialize/de-serialize routines to fill up the struct.
There isn't anything in C to declare a placeholder/hole without a name in a structure or something with a name that is unreadable (const could help but with write protection only). And I don't see anything in gcc's extensions that could help here.
But you could additionally scramble the name by using the preprocessor, e.g.:
#define GLUE(X,Y,Z) X ## Y ## Z
#ifdef __GNUC__
#define SCRAMBLE(X) GLUE(X,_,__COUNTER__)
#else
#define SCRAMBLE(X) GLUE(X,_,__LINE__)
#endif
typedef volatile struct
{
uint8 BDH;
uint8 BDL;
// ...
uint8 IR;
uint8 SCRAMBLE(RESERVED0);
// ...
} RegisterStruct;
I have a C structure defined somewhere outside my code. Can I define a packed version of the same structure? If I define my own structure from the start, that is easy:
struct test {
// members
} __attribute__((packed));
I defined a simple structure and tried two possibilities, this:
struct test {
int x;
double y;
char z;
};
struct test_p {
struct test __attribute__((packed)) s;
};
and this:
struct test {
int x;
double y;
char z;
};
struct test_p {
struct test p;
} __attribute__((packed));
However, neither of these work (both compile fine though) printing sizeof(struct test_p)=24 on my system (I use gcc 4.8.2 on a 64-bit machine) which is the same as sizeof(struct test). Is there a way to achieve the desired effect?
Just in case you were wondering: I want to parse packets received over network which are just packed structures. The thing is, I can't modify the header file because it is a part of a third-party library, and the structure itself contains too many fields to copy them one by one. I can certainly copy the structure definition to my own header and make the packed version -- actually it is the solution I'm using now -- but I was just wondering if there is a more concise solution which does not involve copying the whole definition.
The gcc has introduced the __attribute__((packed)) precisely to avoid the dangerous effects you are seeking: the definition of the structure should binary compatible between all the user applications and libraries which use the same definition.
But the gcc also provides a way to do the packing the old fashioned, dangerous way - #pragma pack(push,n) and #pragma pack(pop). It would work reliably only if the 3rd party header file contains solely the structure definition, or you do not use anything else from the header. Use them like that:
#pragma pack(push,1)
#include "theheader.h"
#pragma pack(pop)
Otherwise, I personally would have simply copy-pasted the structure definition, renamed it, and added __attribute__((packed)) in my own header. Packing with pragmas the whole header is really a dirty hack. And 3rd party headers might change in unexpected ways, contributing to the bit rot.
How can I disable structure padding in C without using pragma?
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.
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
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.
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.
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;
}
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.