Data layouts used by C compilers (the alignment concept) - c

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.

Related

Structure padding in c size related query [duplicate]

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.

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)

Write 9 bits binary data in C

I am trying to write to a file binary data that does not fit in 8 bits. From what I understand you can write binary data of any length if you can group it in a predefined length of 8, 16, 32,64.
Is there a way to write just 9 bits to a file? Or two values of 9 bits?
I have one value in the range -+32768 and 3 values in the range +-256. What would be the way to save most space?
Thank you
No, I don't think there's any way using C's file I/O API:s to express storing less than 1 char of data, which will typically be 8 bits.
If you're on a 9-bit system, where CHAR_BIT really is 9, then it will be trivial.
If what you're really asking is "how can I store a number that has a limited range using the precise number of bits needed", inside a possibly larger file, then that's of course very possible.
This is often called bitstreaming and is a good way to optimize the space used for some information. Encoding/decoding bitstream formats requires you to keep track of how many bits you have "consumed" of the current input/output byte in the actual file. It's a bit complicated but not very hard.
Basically, you'll need:
A byte stream s, i.e. something you can put bytes into, such as a FILE *.
A bit index i, i.e. an unsigned value that keeps track of how many bits you've emitted.
A current byte x, into which bits can be put, each time incrementing i. When i reaches CHAR_BIT, write it to s and reset i to zero.
You cannot store values in the range –256 to +256 in nine bits either. That is 513 values, and nine bits can only distinguish 512 values.
If your actual ranges are –32768 to +32767 and –256 to +255, then you can use bit-fields to pack them into a single structure:
struct MyStruct
{
int a : 16;
int b : 9;
int c : 9;
int d : 9;
};
Objects such as this will still be rounded up to a whole number of bytes, so the above will have six bytes on typical systems, since it uses 43 bits total, and the next whole number of eight-bit bytes has 48 bits.
You can either accept this padding of 43 bits to 48 or use more complicated code to concatenate bits further before writing to a file. This requires additional code to assemble bits into sequences of bytes. It is rarely worth the effort, since storage space is currently cheap.
You can apply the principle of base64 (just enlarging your base, not making it smaller).
Every value will be written to two bytes and and combined with the last/next byte by shift and or operations.
I hope this very abstract description helps you.

Storing an integer and bit in a single word

I was reading through a presentation on the implementation of malloc, and on slide 7 it suggests storing a regions size and availability in a single word to save space. The alternative is to use two words, which is wasteful as the availability bit only needs to be 0 or 1.
This is the given explanation:
If blocks are aligned, low-order address bits are always 0
Why store an always-0 bit?
Use it as allocated/free flag! When reading size word, must mask out this bit
http://courses.engr.illinois.edu/cs241/sp2012/lectures/09-malloc.pdf
But I'm not really understanding how this works and how it could be implemented in C. Why is one bit of the size integer always 0?
If blocks are aligned, low-order address bits are always 0
This is the key to understanding what it going on. Many CPUs require that multibyte primitive values be stored at addresses divisible by the number of bytes in the primitive: 16-bit primitives need to be stored at even addresses; 32-bit ints need to be stored at addresses divisible by four, and so on. An attempt to access an int through a pointer that corresponds to an odd address results in a bus error.
In systems like that malloc must always return an address suitable for storing any primitive supported by the given CPU. Therefore, if CPU supports 32-bit integers, all addresses returned by malloc must be divisible by 4. Such addresses are said to be aligned. To comply, malloc implementations pad sizes blocks requested by the program by 0 to 3 bytes at the end to have length divisible by 4. As a consequence of this decision, the last two bits of an address of an aligned block will always be zero. An implementation of malloc can use these bits for its own purposes, as long as they are "masked out" before returning the result to callers.
malloc(3) (as specified by Posix) should
return a fresh block of memory; or NULL on failure; the returned pointer is not an alias of any other pointer in the program
return a suitably aligned block of memory. Alignment constraints are compiler, ABI, and processor specific. (Often, the alignment should be two words).
The size is not always zero. (actually, it is never zero). You could round it up to a multiple of two words, and use the last bit as a used/free bit.
However, pointers returned by malloc should be suitably aligned, e.g. to 8 bytes. So their bottom 3 bits are zero, and the allocated size in bytes of the malloc-ed zone is a multiple of 8 bytes (above the requested size passed to malloc), so the last 3 bits are zero (and you could use the last bit for other purposes, e.g. a used/free bit).
Why is one bit of the size integer always 0?
I see why this is confusing, but I don't think that's what they're saying on slide 7. They're saying that the low-order address bits are always 0.
Memory addresses of objects are aligned to specific boundaries, which means objects are aligned to a memory address that is a multiple of their size.
So a 64-bit integer is aligned to an eight-byte boundary;
0x7fff315470d8
If a pointer is always aligned to an eight-byte boundary, then the low-order three bits are always zero. ie: 0x816 = 10002
Basically, you can stick whatever you want in those low-order bits, so long as you take them out before dereferencing the pointer. In the 64-bit case you have 3 bits that are always 0, so you can store 3 "flags". In the case of this power point, they're saying take that lowest bit and use it for an "allocated" flag. Stick a 1 in it as long as the memory is allocated, mask it out when you send the pointer to the user.

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