I am trying to implement a 24-bit integral datatype using a c++ struct. I want its size to be 24 bits / 3 bytes -- not padded into a 4 byte int. I am using Visual Studio Community 2019's compiler.
I have tried using #pragma pack
to prevent this as shown below, but sizeof( int24 )
still returns 4.
#pragma pack(push, 1)
struct int24{
unsigned int data : 24;
};
#pragma pack(pop)
How can I get the struct to have a size of 3 bytes? I want to avoid using an array of unsigned chars if possible.
According to my understanding of the #pragma pack
documentation it is only related to adding padding bytes between (or after) members in a structure, and not to the size allocated for a member itself.
In order to achieve what you want you can use a struct holding a std::array
of 3 bytes, with accessors for converting a uint32_t
value to/from it:
#include <iostream>
#include <array>
#include <cstdint>
struct int24 {
explicit int24(uint32_t value)
{
set(value);
}
void set(uint32_t value)
{
bytes[0] = static_cast<uint8_t>(value & 0x000000ff);
bytes[1] = static_cast<uint8_t>((value & 0x0000ff00) >> 8);
bytes[2] = static_cast<uint8_t>((value & 0x00ff0000) >> 16);
}
uint32_t get()
{
uint32_t value = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16);
return value;
}
private:
std::array<uint8_t,3> bytes;
};
int main()
{
std::cout << sizeof(int24) << std::endl;
int24 i24{ 12345 };
std::cout << i24.get();
}
Output:
3
12345
set
method that the uint32_t
value can actually be represented using 24 bits (using an exception or some other error handling method).Note that this solution is dependant on the Endianness of your system.