I'm reading the c code:
void **alignedData = (void **)(((size_t)temp + aligned - 1)&-aligned);
I do not known the means, especially the &- part.
Can anyone explain it?
Thanks!
When using this, aligned should be an unsigned type (or the C implementation should be using two’s complement) and have a value that is a power of two. Then this code calculates an amount of memory to be allocated:
(size_t) temp converts temp to the unsigned type size_t, which is suitable for working with sizes. This will be a number of bytes to be allocated.
(size_t) temp + aligned - 1 adds enough bytes to guarantee a multiple of aligned falls somewhere between the numbers temp and temp + aligned - 1, inclusive. For example, if temp is 37 and aligned is 8, then between 37 and 44 (37+8−1), there is a multiple of 8 (40).
-aligned makes a bit mask with 1 in each bit position that is a multiple of aligned and 0 in the lower bits. For example, if aligned is 8, then the bits that represent -aligned are 111…111000, because the 000 bits at the end represent values of 1, 2, and 4, while the other bits represent values of 8, 16, 32, and so on.
The & (bitwise AND) of (size_t) temp + aligned - 1 with -aligned then clears the low bits, leaving only bits that are multiples of aligned. Thus, it produces the multiple of aligned that is in the interval. For example, with the values of 37 and 8 mentioned before, ((size_t) temp + aligned - 1) & -aligned produces 40.
Thus, this expression produces the value of temp rounded up to the next multiple of aligned. It says “Calculate the number of bytes we need to allocate that is at least temp bytes and is a multiple of aligned.”
After this, the code converts this number to the type void ** and uses it to initialize void **alignedData. That is bad C code. There is generally no good reason for it. A number of bytes like this should not be used as any kind of pointer. The code may be attempting to “smuggle” this value through a data type it is compelled to use by some other software, but there is likely a better way to do it, such as by allocating memory to hold the value and supplying a pointer to that memory instead of trying to convert the value directly. Finding a better solution requires knowing more context of the code.
Related
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.
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)
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.
Firstly, I understand byte padding in structs. But I have still a small test contain a double field in struct and I don't know how to explain this :
typedef struct {
char a;
double b;
}data;
typedef struct{
char a;
int b;
}single;
int main(){
printf("%d\n",sizeof(double));
printf("%d\n",sizeof(single));
printf("%d\n",sizeof(data));
}
Through out this test, the answer is : 8 8 and 16.
Why this result make me thinking ?
By second test, we can see size of word on my machine is 4 bytes.
By first test, we can see size of double is 8 bytes.
So, at the struct data : the result should be 12 bytes : 4 bytes for char and 8 bytes for double.
But, I don't know why the result is 16 bytes. (So strange with me)
Please explain it for me, thanks :)
It's sixteen bytes so that if you have an array of datas, the double values can all be aligned on 8-byte boundaries. Aligning data properly in memory can make a big difference in performance. Misaligned data can be slower to operate on, and slower to fetch and store.
The procedure typically used for laying out data in a struct is essentially this:
Set Offset = 0.
For each member in the struct: Let A be its alignment requirement (e.g., 1, 2, 4, or 8 bytes, possibly more). Add to Offset the number of bytes needed to make it a multiple of A. (Given that A is a power of two, this can be done with Offset += -Offset & A-1, assuming two’s complement for the negation.) Assign the current value of Offset to be the offset of this member. Add the size of the member to Offset.
After processing all members: Let A be the greatest alignment requirement of any member. Add to Offset the number of bytes needed to make it a multiple of A. This final value of Offset is the size of the struct.
As Earnest Friedman-Hill stated, the last step adds padding to the end of the struct so that, in an array of them, each struct begins at the required alignment.
So, for a struct such as struct { char c; double d; int32_t i; }, on a typical implementation, you have:
Set Offset to 0.
char requires alignment of 1, so Offset is already a multiple of 1 (0•1 is 0). Put c at this offset, 0. Add the size of c, 1, to Offset, making it 1.
double requires alignment of 8, so add 7 to Offset, making it 8. Put d at this offset, 8. Add the size of d, 8, to Offset, making it 16.
int requires alignment of 4, so Offset is already a multiple of 4 (4•4 is 16). Put i at this offset, 16. Add the size of i, 4, to Offset, making it 20.
At the end, the largest alignment required was 8, so add 4 to Offset, making it 24. The size of this struct is 24 bytes.
Observe that the above has nothing to do with any word size of the machine. It only uses the alignment requirement of each member. The alignment requirement can be different for each type, and it can be different from the size of the type, and the above will still work.
(The algorithm breaks if alignment requirements are not powers of two. That could be fixed by making the last step increase the offset to be a multiple of the least common multiple of all the alignments.)
What is strange to you (or I'm missing something)?
The logic is the same (the padding is according to the "biggest" primitive field in the struct (I mean - int, double, char, etc.))
As in single, you have
1 (sizeof(char)) + 3 (padding) + 4 (sizeof(int))
it's the same in data:
1 (sizeof(char)) +
7 (padding, it's sizeof(double) - sizeof(char)) +
8 (sizeof(double))
which is 16.
The compiler probably aligns all structure sizes to be a multiple of 8
Alignment is up to the compiler unless you explicitly specify it using compiler specific directives.
Variables aren't necessarily word aligned. Sometimes they're double word aligned for efficieny. In the particular case of floating points, they can be aligned to even higher values so that SSE will work.
language is C with gcc compiler
if i make a struct like so
struct test {
char item_1[2];
char item_3[4];
char item_4[2];
char item_5[2];
char item_6[4];
};
and i do a sizeof(struct test) it returns 14(bytes). which is the expected result.
but if i do
struct test {
int16_t item_1;
int32_t item_3;
int16_t item_4;
int16_t item_5;
int32_t item_6;
};
sizeof(struct test) will return something strange like 44. when i debug using gnu ddd i can see inside the structure and see that it all looks normal and all items have the expected number of bytes.
so why is the sizeof operator returning a unexpected value ?
You have mixed 32/16 bit integers.
int16_t item_1[2]; // 2 * 2 = 4
int32_t item_3[4]; // 4 * 4 = 16
int16_t item_4[2]; // 2 * 2 = 4
int16_t item_5[2]; // 2 * 2 = 4
int32_t item_6[4]; // 4 * 4 = 16
// sum = 44
Compilers may insert padding between struct members, or after the last member. This is normally done to satisfy alignment requirements. For example, an int32_t object might require 4-byte alignment, so the compiler inserts 2 bytes of padding between the first and second members. The details will vary depending on the platform.
compiler is required to insert padding between structure members to align each member on its type's boundary and to order the structure's members as written. If you reorder them such that the largest members are at the beginning of the structure definition, they will be the same size. But since you're trying it with arrays of char, I'm guessing you don't have the structure's original definition, and you're trying to access some externally defined and created object's fields. In that case, I suggest you either obtain the proper headers or use the char[] version and cast char* to whatever type it really is.
The alignment issue is because modern 32-bit CPU's work in 32-bit word sizes on 32-bit address boundaries. If a 32-bit word on a 32-bit boundary contains 2 16-bit values, this results in extra instructions being required to obtain the correct 16-bits (i.e. masking and shifting so that the correct 16-bits are all that remains). If a 32-bit word is split across a 32-bit boundary then there is even more work to do to retrieve it.
By default the trade-off is to have faster programs and not use the memory as efficiently as possible. If an extra couple of instructions are needed everywhere where a structure member is used then this will probably use more memory than tighter packing the structure saves so whilst not obvious at first it's the correct choice.
If you have a requirement to store structures efficiently (at a cost to performance) then "#pragma pack" allows you to tighter pack members, but it results in bigger slower programs.
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
http://www.cplusplus.com/forum/general/14659/
struct test {
int16_t item_1[2]; // 2 * 16 +
int32_t item_3[4]; // 4 * 32 +
int16_t item_4[2]; // 2 * 16 +
int16_t item_5[2]; // 2 * 16 +
int32_t item_6[4]; // 4 * 32
// total = 352
};
352 bits divided by 8 (8 bits go into one byte) is 44 bytes.