Reputation: 559
I have a struct that is supposed to be 8 byte in size.
struct Slot {
uint8_t T;
uint8_t S;
uint32_t O : 24;
uint32_t L : 24;
}
However, sizeof(Slot)
tells me the size is 12 byte.
So the compiler seems to pad the data although it shouldn't be necessary (probably because the 24-bit cannot be aligned properly).
A hacky solution would be to use 3 one-byte fields instead of a single three-byte field:
struct Slot2 {
uint8_t T;
uint8_t S;
uint8_t O1;
uint8_t O2;
uint8_t O3;
uint8_t L1;
uint8_t L2;
uint8_t L3;
}; // sizeof(Slot2) = 8
Is there any other way to achieve this?
Upvotes: 2
Views: 1638
Reputation: 9837
On MSVC the following works and keeps your variable orders the same:
struct Slot {
uint64_t T : 8;
uint64_t S : 8;
uint64_t O : 24;
uint64_t L : 24;
};
This is not guaranteed across compilers though. YMMV on other compilers.
Upvotes: 0
Reputation: 1240
With this compiler dependant solution (works with gcc, msvc) the struct will be 8 bytes:
#pragma pack(push, 1)
struct Slot {
uint8_t T;
uint8_t S;
uint32_t O : 24;
uint32_t L : 24;
};
#pragma pack(pop)
This will set the alignment of the struct to 1 byte.
Upvotes: 0
Reputation: 213892
There is no way anyone can tell what your code will do or how the data will end up in memory, because the behavior of bit fields is poorly specified by the C standard. See this.
uint32_t
for a bit field.The solution is to not use bit fields at all. Use the bitwise operators instead.
Upvotes: 3
Reputation: 52538
Your "hack" solution is exactly the right one. I suspect that the layout is determined by some outside factors, so you won't be able to map this to a struct in any better way. I suspect the order of bytes in your 24 bit numbers is also determined by the outside, and not by your compiler.
To handle that kind of situation, a struct of bytes or just an array of bytes is the easiest and portable solution.
Upvotes: 2
Reputation: 34585
This gives size 8 bytes on MSVC without packing pragma.
struct Slot {
uint32_t O : 24;
uint32_t T : 8;
uint32_t L : 24;
uint32_t S : 8;
};
Upvotes: 3
Reputation: 134336
I think, what you want, 8
bytes, is not something that the C
standard can gurantee, with your first definition.
Related: from C11
standard, Chapter §6.7.2.1,
An implementation may allocate any addressable storage unit large enough to hold a bitfield. 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.
You can have a way out however, if you can adjust the variable so that they can fit properly in 32-bit alignment, then
24 + 8 + 24 + 8
= 64
bits = 8
bytes.
you can have a structure of size 8
bytes.
Upvotes: 0
Reputation: 5387
Try something like as shown below:
struct Slot {
uint32_t O : 24;
uint8_t T;
uint32_t L : 24;
uint8_t S;
};
Upvotes: -3