struct {
uint8_t foo;
uint8_t bar;
uint8_t baz;
uint8_t foos[252];
uint8_t somethingOrOther;
} A;
struct {
uint8_t foo;
uint8_t bar;
uint8_t baz;
uint8_t somethingOrOther;
uint8_t foos[252];
} B;
Does it matter that I've put foos on byte 3 in the first example, vs on byte 4 in B?
Does an array in C have to start aligned?
Is the size of this struct 256 bytes exactly?
Given that the data type is uint8_t (equivalent to unsigned char), there is no need for padding in the structure, regardless of how it is ordered. So, you can reasonably assume in this case that every compiler will make that structure into 256 bytes, regardless of the order of the elements.
If there were data elements of different sizes, then you might well get padding added and the size of the structure might vary depending on the order of the elements.
As the good book says (C11 section 6.7.2.1 paragraph 14):
Each non-bit-field member of a structure or union object is aligned in
an implementation- defined manner appropriate to its type... There
may be unnamed padding within a structure object
You didn't "put foos on byte 3" - apart from the fact that the first element is always on byte 0, you have no real control over what byte an element will be put on. The compiler can give each field a full machine word or more if it thinks that will provide the most efficient accesses. If so, it will allocate "padding" bytes in between - unused space.
Note that this only applies to structs; arrays themselves do not add any padding bytes (if they did, the pointer arithmetic/indexing rule wouldn't work), so you can be sure that the size of foos itself is exactly the declared size, and know the exact alignment of each numbered element.
No, it doesn't matter.
Pretty much every compiler out there will align struct fields to a natural boundary appropriate for the target architecture, by inserting hidden "padding bytes" between fields where necessary.
Specifically, since you're using only uint8_t, there will be no padding bytes inserted - every field already falls on a naturally-aligned boundary. (Everything is a multiple of one.)
Both of the structs you've shown are exactly 256 bytes in size. You can confirm this like so:
int main(void)
{
printf("sizeof(struct A)=%zu \n", sizeof(struct A));
printf("sizeof(struct B)=%zu \n", sizeof(struct B));
}
You can prevent this padding from being added by "packing" the structure:
Microsoft Visual C uses #pragma pack(1)
GCC uses __attribute__((packed))
Do note that doing this on a structure with unaligned members can have a serious impact on the performance of your program.
Related
I'm new to structures and was learning how to find the size of structures. I'm aware of how padding comes in to play in order to properly align the memory. From what I've understood, the alignment is done so that the size in memory comes out to be a multiple of 4.
I tried the following piece of code on GCC.
struct books{
short int number;
char name[3];
}book;
printf("%lu",sizeof(book));
Initially I had thought that the short int would occupy 2 bytes, followed by the character array starting at the third memory location from the beginning. The character array then would need a padding of 3 bytes which would give a size of 8. Something like this, where each word represents a byte in memory.
short short char char
char padding padding padding
However on running it gives a size of 6, which confuses me.
Any help would be appreciated, thanks!
Generally, padding is inserted to allow for aligned access of the internal elements of the structure, not to allow the entire structure to be a size of multiple words. Alignment is a compiler implementation issue, not a requirement of the C standard.
So, the char elements which are 3 bytes in length, need no alignment because they are byte elements.
It is preferred, though not required, that the short element needs to be aligned on a short boundary -- which means an even address. By aligning it on a short boundary, the compiler can issue a single load short instruction rather than having to load a word, mask, and then shift.
In this case, the padding is probably, but not necessarily, happening at the end rather than in the middle. You will have to write code to dump the address of the elements to determine where padding is taking place.
EDIT: . As #Euguen Sh mentions, even if you discover the padding scheme that the compiler is using for the structure, the compiler could modify that in a different version of the compiler.
It is unwise to count on the padding scheme of the compiler. There are always methods to access the elements in such a way that you do not guess at alignments.
The sizeof() operator is used to allow you to see how much memory is used AND to know how much will be added to a ptr to the structure if that pointer is incremented by 1 (ptr++).
EDIT 2, Packing: Structures may be packed to prevent padding using the __packed__ attribute. When designing a structure, it is wise to use elements that naturally pack. This is especially important when sending data over a communications link. A carefully designed structure avoids the need for padding in the middle of the strucuture. A poorly designed structure which is then compiled with the __packed__ attribute may have internal elements that are not naturally aligned. One might do this to ensure that the structure will transmit across a wire as it was originally designed. This type of effort has diminished with the introduction of JSON for transmission of data over a wire.
#include <stdalign.h>
#include <assert.h>
The size of a struct is always divisible by the maximum alignment of the members (which must be a power of two).
If you have a struct with char and short the alignment is 2, because the alignment of short is two, if you have a struct, only out of chars it has an alignment of 1.
There are multiple ways to manipulate the alignment:
alignas(4) char[4]; // this can hold 32-bit ints
This is nonstandart, but available in most compilers (GCC, Clang, ...):
struct A {
char a;
short b;
};
struct __attribute__((packed)) B {
char a;
short b;
};
static_assert(sizeof(struct A) == 4);
static_assert(alignof(struct A) == 2);
static_assert(sizeof(struct B) == 3);
static_assert(alignof(struct B) == 1);
Usually compilers follow ABI of the target architecture.
It defines alignments of structures and primitive datatypes. And that affects to needed padding and sizes of structures. Because alignment is multiple of 4 in many architectures, size of structures are too.
Compilers may offer some attributes/options for changing alignments more or less directly.
For example gcc and clang offers: __attribute__ ((packed))
In GCC C, how can I get an array of packed structs, where each entry in the array is aligned?
(FWIW, this is on a PIC32, using the MIPS4000 architecture).
I have this (simplified):
typedef struct __attribute__((packed))
{
uint8_t frameLength;
unsigned frameType :3;
uint8_t payloadBytes;
uint8_t payload[RADIO_RX_PAYLOAD_WORST];
} RADIO_PACKET;
RADIO_PACKETs are packed internally.
Then I have RADIO_PACKET_QUEUE, which is a queue of RADIO_PACKETs:
typedef struct
{
short read; // next buffer to read
short write; // next buffer to write
short count; // number of packets stored in q
short buffers; // number of buffers allocated in q
RADIO_PACKET q[RADIO_RX_PACKET_BUFFERS];
} RADIO_PACKET_QUEUE;
I want each RADIO_PACKET in the array q[] to start at an aligned address (modulo 4 address).
But right now GCC doesn't align them, so I get address exceptions when trying to read q[n] as a word. For example, this gives an exception:
RADIO_PACKET_QUEUE rpq;
int foo = *(int*) &(rpq.q[1]);
Perhaps this is because of the way I declared RADIO_PACKET as packed.
I want each RADIO_PACKET to remain packed internally, but want GCC to add padding as needed after each array element so each RADIO_PACKET starts at an aligned address.
How can I do this?
Since you specify that you are using GCC, you should be looking at type attributes. In particular, if you want RADIO_PACKETs to be aligned on 4-byte (or wider) boundaries, then you would use __attribute__((aligned (4))) on the type. When applied to a struct, it describes the alignment of instances of the overall struct, not (directly) the alignment of any individual members, so it is possible to use it together with attribute packed:
typedef struct __attribute__((aligned(4), packed))
{
uint8_t frameLength;
unsigned frameType :3;
uint8_t payloadBytes;
uint8_t payload[RADIO_RX_PAYLOAD_WORST];
} RADIO_PACKET;
The packed attribute prevents padding between structure elements, but it does not prevent trailing padding in the structure representation, exactly as is necessary for ensuring the required alignment for every element of an array of the specified type. You should not then need to do anything special in the declaration of RADIO_PACKET_QUEUE.
This is a lot cleaner and clearer than the alternative you came up with, but it is GCC-specific. Since you were GCC-specific already, I don't see that being a problem.
You can wrap your packed structure, inside another unaligned structure. Then you do array from this unaligned structures.
Solution 2 could be, to add dummy member char[] at the end of the packed structure. In this case you will need to calculate it somehow, probably manually.
I also will suggest you to rearrange your structure, by placing longer members first and placing uint8_t members last (assuming you have 16/32 bit members and not doing some HW mapping).
I think I've solved this, based on the hint from #Nick in the question comments.
I added a RADIO_PACKET_ALIGNED wrapper around RADIO_PACKET. This includes calculated padding.
Then I substituted RADIO_PACKET_ALIGNED for RADIO_PACKET in the RADIO_PACKET_QUEUE structure.
Seems to work:
typedef struct
{
RADIO_PACKET packet;
uint8_t padding[3 - (sizeof(RADIO_PACKET) + 3) % 4];
} RADIO_PACKET_ALIGNED;
typedef struct
{
short read; // next buffer to read
short write; // next buffer to write
short count; // number of packets stored in q
short buffers; // number of buffers allocated in q
RADIO_PACKET_ALIGNED q[RADIO_RX_PACKET_BUFFERS];
} RADIO_PACKET_QUEUE;
Thanks to all the commenters!
Edit: A more portable version of the wrapper would use:
uint8_t padding[(sizeof(int) - 1) - (sizeof(RADIO_PACKET) + (sizeof(int) - 1)) % sizeof(int)];
What is the best practice of using variable length array inside a structure?
Say
typedef struct foo_s {
uint32_t data_type;
uint16_t data_len;
uint8_t data[];
} foo_t;
On a x86_64 machine with Gcc 4.8, i got
sizeof(foo_t) == 8, but
offsetof(foo_t, data) == 6
looks like there is a difference there, no padding after data_len, but there is padding for the structure.
Should I keep always keep the largest member last to avoid this? i.e.
typedef struct foo_s {
uint16_t data_len;
uint32_t data_type;
uint8_t data[];
} foo_t;
What's the best practice for using var len array?
Unless you have a particular reason for wanting data to be 4-byte aligned (and if so, why is it a uint8?), the first one is mildly preferable because it'll save you a couple of bytes. For a variable-length structure like this, the value reported by sizeof is not really relevant, for exactly this reason. If you decide to allocate sizeof(foo_t) + data_len bytes for it then you'll be wasting a couple of bytes, but you'd waste them in padding in your second structure definition anyway.
If you want to pack your structs without sacrificing alignment then yes: the best option is to order elements in decreasing or increasing order. The array must be the last element, so here your best option is decreasing order (note that the size win is small, and it only matters if you have a large array of structs, but with a flexible array member you can't have an array of structs).
I was trying to give a "logical" counter-example to this answer indicating that sorting the members of a struct based on their size would minimize padding, when I encountered what seems to me as illogical.
Imagine the following struct:
struct A
{
int32_t a;
int16_t b;
};
sizeof this struct would normally be padded to 8 bytes to make sure a is aligned for example in an array of struct A.
Now image these other structs:
struct B
{
struct A a, b;
int16_t c, d;
};
struct C
{
struct A a;
int16_t c;
struct A b;
int16_t d;
};
As expected struct B has size 20 due to padding. However, I would have expected struct C to have size 16 since padding could be avoided, but ideone and gcc (with or without optimization) give a size of 24 bytes, clearly padding 2 bytes after each of the members.
My reasoning is that struct A in reality has only 6 bytes and should be padded when necessary, for example in an array of struct A or its usage in struct B. However, in struct C padding of struct A is unnecessary and c could have been placed where the padding of a could have been and the same with d and b.
Why doesn't the compiler minimize the padding by putting c where the padding of a would be?
P.S. I understand that sizeof(struct A) must return 8. Otherwise something like memset(array_of_A, 0, N * sizeof *array_of_A) won't work properly since array_of_A would contain padding while N * sizeof *array_of_A would ignore that padding.
The only thing I can think of that could be a problem is that with the optimization above then sizeof(struct C) would be smaller than the sizeof of all its members. However, I can't think of a case where such a thing could become a problem (i.e. a usage that is not based on undefined behavior).
struct C someC;
struct A someA;
*(struct A*)&(someC.a) = someA;
The assignment above may fail (mistakenly write to someC.c) if the padding you describe is supported by compilers.
EDITED: The example above relies on the compiler behavior when assigning structs. As I have known (an just checked) gcc copies as the struct is a flat region of memory, which is not member-wise.
EDITED: Changed from "would fail" to "may fail" since it's not defined if the padding bits shall be copied, see item 6 of section 6.2.6.1 of ISO_IEC_9899_2011:
When a value is stored in an object of structure or union type, including in a member
object, the bytes of the object representation that correspond to any padding bytes take
unspecified values.51)
and footnote 51):
51) Thus, for example, structure assignment need not copy any padding bits.
memcpy(&someC.a, &someA, sizeof(someC.a)) would write over someC.c.
That's what I was trying to get at with my comment about sizeof()'s having
to be different. For that memcpy() to work, sizeof(someC.a) would have to
be different from sizeof(someA) which just seems to be asking for a lot of
trouble and hard to find bugs.
Following GCC __attribute__(packed ) will pack to byte boundary, aligned is used for which purpose :--
u8 rx_buf[14] __attribute__((aligned(8)));
struct S { short f[3]; } __attribute__ ((aligned (8)));
above array will be of 16 byte, am I right.
means sizeof(rx_buff) will be 16 byte .. i.e 2 byte alignment at end
The answer to your question is no. The aligned attribute does not change the sizes of variables it is applied to, but the situation is slightly different for structure members. To quote the manual,
aligned (alignment)
This attribute specifies a minimum alignment for the variable or structure field, measured in bytes. For example, the declaration:
int x __attribute__ ((aligned (16))) = 0;
causes the compiler to allocate the global variable x on a 16-byte boundary.
and,
packed
The packed attribute specifies that a variable or structure field should have the smallest possible alignment — one byte for a variable,
and one bit for a field, unless you specify a larger value with the
aligned attribute.
Here is a structure in which the field x is packed, so that it immediately follows a:
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
Note that the aligned attribute may change the memory layout of structures, by inserting padding between members. Subsequently, the size of the structure will change. For instance:
struct t {
uint8_t a __attribute__((aligned(16))); /* one byte plus 15 as padding here */
uint16_t b __attribute__((aligned(16)));
};
would lead to 15 bytes of padding after a whereas the default alignment for the target architecture might have resulted in less. If you specified the packed attribute for the structure and lost the aligned attributes the structure would have a size of 3 bytes.
Here's an illustration of how the memory layout of a structure might look like in each case.
struct t with no attributes and default alignment on 8-byte boundary:
+-+-------+--+-------+
|a| |bb| |
+-+-------+--+-------+
struct t when a and b are aligned on 16-byte boundaries:
+-+---------------+--+---------------+
|a| padding |bb| padding |
+-+---------------+--+---------------+
struct t when a and b have no alignment restrictions and t is packed:
+-+--+
|a|bb|
+-+--+
above array will be of 16 byte, am I right.
Incorrect. The array is still 14 bytes long; all that __attribute__((aligned)) does is provide any necessary padding outside the array to align it to an 8-byte boundary. It is impossible to safely assume anything about where this padding exists, or how much of it there is.
As such, sizeof(rx_buf) will remain 14, just as it would have been without the alignment.