Structure padding in c size related query [duplicate] - c

This question already has answers here:
Structure padding and packing
(11 answers)
Closed 6 days ago.
I find a lot of ambiguity while working on structure padding in C.
I need the following :
Trustworthy resource or url to understand structure padding in c.
How memory is allocated to structures, by individual members of by pages (like 1 page=4 bytes for 32 bit machines and 8 bytes for 64 bit machines).
#include <stdio.h>
typedef struct
{
unsigned short Flag;
char DebounceSamples;
unsigned short Device;
char *BufferPtr;
char *OverridePtr;
} IoHwAb_DIN_DescriptorType;
int main()
{
IoHwAb_DIN_DescriptorType tt;
printf("%lu",sizeof(tt));
return 0;
}
When I execute this I see the output is 24 for the size of struct. I kind of understand why, but also I have a confusion. I need a clear explanation on this.

Each object type has some alignment requirement. Any object of that type is required to start at an address that is a multiple of the alignment requirement. Each C implementation may determine its own alignment requirements for its object types, but alignment requirements are usually set for hardware efficiency. Most notably, the requirements are set so that any correctly aligned object will not cross a memory boundary that requires an extra load or store operation.
For example, consider hardware that can perform transfers of data between the processor and memory in four-byte chunks starting at addresses that are multiples of four bytes. The hardware can transfer bytes addressed 0-3 in one operation, bytes addressed 4-7 in one operation, bytes address 8-11 in one operation, and so on. However, if we wanted bytes 6-9, that would require two memory transfer operations, one to get byes 4-7 and one to get bytes 8-11. In this hardware, we would set the alignment requirement of a four-byte int to be four bytes, so that all four bytes of the int are always inside one of these aligned groups.
For a two-byte short, we could allow a short object to be in bytes 5-6 in memory, because we can fetch both bytes in one operation (loading bytes 4-7). However, if we have an array of short with the first in bytes 5-6, then the next would be in 7-8, and we cannot fetch that short in one operation; we would have to get bytes 4-7 and 8-11. So, to ensure that short objects always have good alignment, we require them to start at multiples of two bytes.
Once the alignment requirements are set, the algorithm usually used to lay out a structure is:
Each member in the structure has some size s and some alignment requirement a.
The compiler starts with a size S set to zero and an alignment requirement A set to one (byte).
The compiler processes each member in the structure in order:
Consider the member’s alignment requirement a. If S is not currently a multiple of a, then add just enough bytes to S so that it is a multiple of a. This determines where the member will go; it will go at offset S from the beginning of the structure (for the current value of S).
Set A to the least common multiple1 of A and a.
Add s to S, to set aside space for the member.
When the above process is done for each member, consider the structure’s alignment requirement A. If S is not currently a multiple of A, then add just enough to S so that it is a multiple of A.
The size of the structure is the value of S when the above is done.
Additionally:
If any member is an array, its size is the number of elements multiplied by the size of each element, and its alignment requirement is the alignment requirement of an element.
If any member is a structure, its size and alignment requirement are calculated as above.
If any member is a union, its size is the size of its largest member plus just enough to make it a multiple of the least common multiple1 of the alignments of all the members.
The rules above follow largely from logic; they put each member where it must be to satisfy alignment requirements without using more space than necessary. The C standard allows implementations to add more padding between elements or at the end of the structure, but this is generally not done. (It could be done for special purposes, such as adding padding during debugging to test whether some bug manifests without padding but not with it, to give clues about the nature of the bug.)
In your structure, char is one byte with alignment requirement one byte, unsigned short is probably two bytes with requirement two bytes, and char * is probably eight bytes with requirement eight bytes. Then the structure layout proceeds:
S is zero and A is one byte.
No padding is needed, since S is a multiple of the two-byte requirement for unsigned short Flag.
unsigned short Flag adds two to S and makes A two bytes.
No padding is needed, since S is a multiple of the one-byte requirement for char DebounceSamples.
char DebounceSamples adds one to S, making it three, and does not change A, leaving it two bytes.
One byte of padding is needed, because S is not a multiple of the two-byte requirement for unsigned short Device, so S is increased to four.
unsigned short Device adds two to S, making it six, and does not change A, leaving it two bytes.
Two bytes of padding are needed, because S is not a multiple of the eight-byte requirement for char *BufferPtr, so S is increased to eight.
char *BufferPtr adds eight to S, making it 16, and changes A to eight bytes.
No padding is needed because S is a multiple of the eight-byte requirement for char *OverridePtr.
char *OverridePtr adds eight to S, making it 24, and does not change A.
At the end, the size of the structure is 24 bytes, and its alignment requirement is eight bytes.
Footnote
1 I have worded this for a general case as using the least common multiple of alignment requirements. However, since alignment requirements are always powers of two, the least common multiple of any set of alignment requirements is the largest of them.

Related

Data layouts used by C compilers (the alignment concept)

Below is an excerpt from the red dragon book.
Example 7.3. Figure 7.9 is a simplification of the data layout used by C compilers for two machines that we call Machine 1 and Machine 2.
Machine 1 : The memory of Machine 1 is organized into bytes consisting of 8 bits each. Even though every byte has an address, the instruction set favors short integers being positioned at bytes whose addresses are even, and integers being positioned at addresses that are divisible by 4. The compiler places short integers at even addresses, even if it has to skip a byte as padding in the process. Thus, four bytes, consisting of 32 bits, may be allocated for a character followed by a short integer.
Machine 2: each word consists of 64 bits, and 24 bits are allowed for the address of a word. There are 64 possibilities for the individual bits inside a word, so 6 additional bits are needed to distinguish between them. By design, a pointer to a character on Machine 2 takes 30 bits — 24 to find the word and 6 for the position of the character inside the word. The strong word orientation of the instruction set of Machine 2 has led the compiler to allocate a complete word at a time, even when fewer bits would suffice to represent all possible values of that type; e.g., only 8 bits are needed to represent a character. Hence, under alignment, Fig. 7.9 shows 64 bits for each type. Within each word, the bits for each basic type are in specified positions. Two words consisting of 128 bits would be allocated for a character followed by a short integer, with the character using only 8 of the bits in the first word and the short integer using only 24 of the bits in the second word. □
I found about the concept of alignment here ,here and here. What I could understand from them is as follows: In word addressable CPUs (where size is more than a byte), there certain paddings are introduced in the data objects, such that CPU can efficiently retrieve data from the memory with minimum no. of memory cycles.
Now the Machine 1 here is actually a byte address one. And the conditions in the Machine 1 specification are probably more difficult than a simple word addressable machine having word size of say 4 bytes. In such a 64 bit machine, we need to make sure that our data items are just word aligned ,no more difficulty. But how to find the alignment in systems like Machine 1 (as given in the table above) where the simple concept of word alignment does not work, because it is byte addressable and has much more difficult specifications.
Moreover I find it quite weird that in the row for double the size of the type is more than what is given in the alignment field. Shouldn't alignment(in bits) ≥ size (in bits) ? Because alignment refers to the memory actually allocated for the data object (?).
"each word consists of 64 bits, and 24 bits are allowed for the address of a word. There are 64 possibilities for the individual bits inside a word, so 6 additional bits are needed to distinguish between them. By design, a pointer to a character on Machine 2 takes 30 bits — 24 to find the word and 6 for the position of the character inside the word." - Moreover how should this statement about the concept of the pointers, based on alignment is to be visualized (2^6 = 64, it is fine but how is this 6 bits correlating with the alignment concept)
First of all, the machine 1 is not special at all - it is exactly like a x86-32 or 32-bit ARM.
Moreover I find it quite weird that in the row for double the size of the type is more than what is given in the alignment field. Shouldn't alignment(in bits) ≥ size (in bits) ? Because alignment refers to the memory actually allocated for the data object (?).
No, this isn't true. Alignment means that the address of the lowest addressable byte in the object must be divisible by the given number of bytes.
Additionally, with C, it is also true that within arrays sizeof (ElementType) will need to be greater than or equal to the alignment of each member and sizeof (ElementType) be divisible by alignment, thus the footnote a. Therefore on the latter computer:
struct { char a, b; }
might have sizeof 16 because the characters are in distinct addressable words, whereas
struct { char a[2]; }
could be squeezed into 8 bytes.
how should this statement about the concept of the pointers, based on alignment is to be visualized (2^6 = 64, it is fine but how is this 6 bits correlating with the alignment concept)
As for the character pointers, the 6 bits is bogus. 3 bits are needed to choose one of the 8 bytes within the 8-byte words, so this is an error in the book. An ordinary byte would select just a word with 24 bits, and a character (a byte) pointer would select the word with 24 bits, and one of the 8-bit bytes inside the word with 3 bits.

C - Type Name : Number?

I was wondering what the following code is doing exactly? I know it's something to do with memory alignment but when I ask for the sizeof(vehicle) it prints 20 but the struct's actual size is 22. I just need to understand how this works, thanks!
struct vehicle {
short wheels:8;
short fuelTank : 6;
short weight;
char license[16];
};
printf("\n%d", sizeof(struct vehicle));
20
Memory will be allocated as (assuming memory word size is of 8 bits)
struct vehicle {
short wheels:8; // 1 byte
short fuelTank : 6;
// padd 2 bits to make fuelTank of 1 byte.
short weight; // 2 bytes.
char license[16]; // 16 bytes.
};
1 + 1 + 2 + 16 = 20 bytes.
Consider a machine with a word size of 32bit. The two first fields fit in a whole 16bit word as they occupy 8 + 6 = 14 bits. The second field, while not a bitfield (doesn't have the :<number> thing to allocate space in bits) can fit another 16 bits word to complete a 32 bit word, so the three first fields can pack in a 32bit word (4 bytes) if the architecture allows to access the memory in 16 bit quantities. Finaly, if you add 16 characters to that, this gives the 20 bytes that sizeof operator sends to printf.
Why do you assume the sizeof (struct vehicle) is 22 bytes? You allowed the compiler to print it and it said it's 20. Compilers are free to pad (or not) the structures to achieve better performance. That's an architecture dependency, and as you have not said architecture and compiler used, it is not possible to go further.
For example, 32bit intel arch allows to pad words at even boundaries without performance penalties, so this is a good selection in order to save memory. On other architectures, perhaps it's not allowed to use 16bit integers and data must be padded to fit the third field (leading to 22 bytes for the whole structure)
The only warranty you have when sizing data is that the compiler must allocate enough space to fit everything in an efficient way, so the only thing you can assume from that declaration is that it will occupy at least the minimum space to represent one field of 8 bit, other of 6, a complete short (I'll assume a short is 16 bit) and 16 characters (assuming 8 bits per char) it ammounts to 8 + 6 + 16 + 16*8 = 158 bits minimum.
Suppose we are writing a compiler for D. Knuth MIX machine. As it's stated in his book Fundamental Algorithms, this machine has an unspecified byte size of 64..100 bytes, requiring five to construct one addressable word (plus a binary sign). If you had a byte size independent compiler (one that compiles for any MIX machine, without assumptions of byte size) you have to use no more than 64 possible values per byte, leading to 6 bit per byte. You then would assume the second field fills one complete byte (and the sign drawn from the word it belongs to) and the first field needs two complete bytes (using half of the values for negative values) The third field might be in the second word, filling three complete bytes (6*3 = 18) and the sign of that word. The next 16 chars can begin on the next word, summing up to five complete words, so the whole structure will have 1 + 1 + 4 = 6 words, or 30 bytes. But if you want to handle effectively three signed fields, you'll need three complete words for the three fields (as each has a sign field only) leading to 7 words or 35 bytes.
I have suggested this example because of the particular characteristics of this architecture, that makes one to think on not so uncommon architectures that some time ago where in common use (the first machines ever built where not binary based, like some of these MIX machines)
Note
You can try to print the actual offsets of the fields, to see where in the structure are located and see where the compiler is padding.
#define OFFSET(Typ, field) ((int)&((Typ *)0)->field)
(Note, edited)
This macro will tell you the offset as an int. Use it as OFFSET(struct vehicle, weight) or OFFSET(struct vehicle, license[3])
Note
I had to edit the last macro definition as it complains on some architectures as the conversion of pointer -> int is not always possible (on 64bit architectures, it looses some bits) so it's better to compute the difference of two pointers, which is a proper size_t value, than to convert it directly from pointer.
#define OFFSET(Typ, field) ((char *)&((Typ *)0)->field - (char *)0)

Handling bit arrays in C without padding

I'm writing a C program that runs on the Altera NIOS II processor. The program has to interface to a VHDL module on an FPGA test board through a specific memory location. My interface is provided through a Macro, which specifies a base memory address. The VHDL programmer has allocated 32-bits of memory off of that base address, which I'm to fill with binary data separated into four "elements", i.e. [0-11|12-15|16-23|24-31].
My question is, what is the best way to handle these array "elements" as separate data types. I'd like to declare the entire array as a structure to handle the data and declare the different fields using bit-fields, but it's my understanding that this will introduce padding into the 32 bit array.
it's my understanding that [using bit fields] will introduce padding into the 32 bit array
Using bit fields will not introduce padding, unless you explicitly request it: language standard prohibits the compier from padding in between bit fields:
C99 Standard, section 6.7.2.1.10: If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.
You can force padding to happen by specifying a bit field of zero width, like this:
struct hw_reg {
int a:10;
int :0; // Yes, this is legal.
int b:6;
};
In your case, sufficient space remains after the first 12 bits to allocate the next four, so there will be no padding. If you needed to split the register differently (say, 12-5-7-8), the use of padding would be implementation-defined.
binary data separated into four "elements", i.e.
[0-11|12-15|16-23|24-31].
I'd try as
struct vhdl_data {
uint32_t a : 12; // bits 0-11
uint32_t b : 4; // bits 12-15
uint32_t c : 8; // bits 16-23
uint32_t d : 8; // bits 24-31
};

Bit field manipulation disadvantages

I was reading this link
http://dec.bournemouth.ac.uk/staff/awatson/micro/articles/9907feat2.htm
I could not understand this following statements from the link, Please help me understand about this.
The programmer just writes some macros that shift or mask the
appropriate bits to get what is desired. However, if the data involves
longer binary encoded records, the C API runs into a problem. I have,
over the years, seen many lengthy, complex binary records described
with the short or long integer bit-field definition facilities. C
limits these bit fields to subfields of integer-defined variables,
which implies two limitations: first of all, that bit fields may be no
wider, in bits, than the underlying variable; and secondly, that no
bit field should overlap the underlying variable boundaries. Complex
records are usually composed of several contiguous long integers
populated with bit-subfield definitions.
ANSI-compliant compilers are free to impose these size and alignment
restrictions and to specify, in an implementation-dependent but
predictable way, how bit fields are packed into the underlying machine
word structure. Structure memory alignment often isn’t portable, but
bit field memory is even less so.
What i have understood from these statements is that the macros can be used to mask the bits to left or right shift. But i had this doubt in my mind why do they use macros? - I thought by defining it in macros the portability can be established irrespective of 16-bit or 32-bit OS..Is it true?I could not understand the two disadvantages mentioned in the above statement.1.bit fields may be no wider 2.no bit field should overlap the underlying variable boundaries
and the line,
Complex records are usually composed of several contiguous long integers
populated with bit-subfield definitions.
1.bit fields may be no wider
Let's say you want a bitfield that is 200 bits long.
struct my_struct {
int my_field:200; /* Illegal! No integer type has 200 bits --> compile error!
} v;
2.no bit field should overlap the underlying variable boundaries
Let's say you want two 30 bit bitfields and that the compiler uses a 32 bit integer as the underlying variable.
struct my_struct {
unsigned int my_field1:30;
unsigned int my_field2:30; /* Without padding this field will overlap a 32-bit boundary */
} v;
Ususally, the compiler will add padding automatically, generating a struct with the following layout:
struct my_struct {
unsigned int my_field1:30;
:2 /* padding added by the compiler */
unsigned int my_field2:30; /* Without padding this field will overlap a 32-bit boundary */
:2 /* padding added by the compiler */
} v;

How the size of this structure comes out to be 4 byte

I do have a structure having bit-fields in it.Its comes out to be 2 bytes according to me but its coming out to be 4 .I have read some question related to this here on stackoverflow but not able to relate to my problem.This is structure i do have
struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}
if int type has to be on its memory boundary,then output should be 8 bytes but its showing 4 bytes??
Source: http://geeksforgeeks.org/?p=9705
In sum: it is optimizing the packing of bits (that's what bit-fields are meant for) as maximum as possible without compromising on alignment.
A variable’s data alignment deals with the way the data stored in these banks. For example, the natural alignment of int on 32-bit machine is 4 bytes. When a data type is naturally aligned, the CPU fetches it in minimum read cycles.
Similarly, the natural alignment of short int is 2 bytes. It means, a short int can be stored in bank 0 – bank 1 pair or bank 2 – bank 3 pair. A double requires 8 bytes, and occupies two rows in the memory banks. Any misalignment of double will force more than two read cycles to fetch double data.
Note that a double variable will be allocated on 8 byte boundary on 32 bit machine and requires two memory read cycles. On a 64 bit machine, based on number of banks, double variable will be allocated on 8 byte boundary and requires only one memory read cycle.
So the compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure. If you remove char from your struct, you will still get 4 bytes.
In your struct, char is 1 byte aligned. It is followed by an int bit-field, which is 4 byte aligned for integers, but you defined a bit-field.
8 bits = 1 byte. Char can be any byte boundary. So Char + Int:8 = 2 bytes. Well, that's an odd byte boundary so the compiler adds an additional 2 bytes to maintain the 4-byte boundary.
For it to be 8 bytes, you would have to declare an actual int (4 bytes) and a char (1 byte). That's 5 bytes. Well that's another odd byte boundary, so the struct is padded to 8 bytes.
What I have commonly done in the past to control the padding is to place fillers in between my struct to always maintain the 4 byte boundary. So if I have a struct like this:
struct s {
int id;
char b;
};
I am going to insert allocation as follows:
struct d {
int id;
char b;
char temp[3];
}
That would give me a struct with a size of 4 bytes + 1 byte + 3 bytes = 8 bytes! This way I can ensure that my struct is padded the way I want it, especially if I transmit it somewhere over the network. Also, if I ever change my implementation (such as if I were to maybe save this struct into a binary file, the fillers were there from the beginning and so as long as I maintain my initial structure, all is well!)
Finally, you can read this post on C Structure size with bit-fields for more explanation.
int c:8; means that you are declaring a bit-field with the size of 8 bits. Since the alignemt on 32 bit systems is normally 4 bytes (=32 bits) your object will appear to have 4 bytes instead of 2 bytes (char + 8 bit).
But if you specify that c should occupy 8 bits, it's not really an int, is it? The size of c + b is 2 bytes, but your compiler pads the struct to 4 bytes.
They alignment of fields in a struct is compiler/platform dependent.
Maybe your compiler uses 16-bit integers for bitfields less than or equal to 16 bits in length, maybe it never aligns structs on anything smaller than a 4-byte boundary.
Bottom line: If you want to know how struct fields are aligned you should read the documentation for the compiler and platform you are using.
In generic, platform-independent C, you can never know the size of a struct/union nor the size of a bit-field. The compiler is free to add as many padding bytes as it likes anywhere inside the struct/union/bit-field, except at the very first memory location.
In addition, the compiler is also free to add any number of padding bits to a bit-field, and may put them anywhere it likes, because which bit is msb and lsb is not defined by C.
When it comes to bit-fields, you are left out in the cold by the C language, there is no standard for them. You must read compiler documentation in detail to know how they will behave on your specific platform, and they are completely non-portable.
The sensible solution is to never ever use bit fields, they are a reduntant feature of C. Instead, use bit-wise operators. Bit-wise operators and in-depth documented bit-fields will generate the same machine code (non-documented bit-fields are free to result in quite arbitrary code). But bit-wise operators are guaranteed to work the same on any compiler/system in the world.

Resources