1

I am trying to port embed code in windows platform. I have come across below problem I am posting a sample code here. here even after I use int24 size remains 12 bytes in windows why ?

struct INT24
{
    INT32 data : 24;
};

struct myStruct
{
    INT32 a;
    INT32 b;
    INT24 c;
};

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned char myArr[11] = { 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF };
    myStruct *p = (myStruct*)myArr;
    cout << sizeof(*p);
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
vivek
  • 849
  • 4
  • 14
  • 24

2 Answers2

3

There are two reasons, each of which would be enough by themselves.

  • Presumably the size of INT32 is 4 bytes. The size of INT24 is also 4 bytes, because it contains a INT32 bit field. Since, myStruct contains 3 members of size 4, its size must therefore be at least 12.
  • Presumably the alignment requirement of INT32 is 4. So, even if the size of INT24 were 3, the size of myStruct would still have to be 12, because it must have at least the alignment requirement of INT32 and therefore the size of myStruct must be padded to the nearest multiple of 4.

any way or workaround ?

This is implementation specific, but the following hack may work for some compilers/cpu combinations. See the manual of your compiler for the syntax for similar feature, and the manual for your target cpu whether it supports unaligned memory access. Also do realize that unaligned memory access does have a performance penalty.

#pragma pack(push, 1)
struct INT24
{
 INT32 data : 24;
};
#pragma pack(pop)

#pragma pack(push, 1)
struct myStruct
{
INT32 a;
INT32 b;
INT24 c;
};
#pragma pack(pop)

Packing a bit field might not work the same in all compilers. Be sure to check how yours behaves.

I think that a standard compliant way would be to store char arrays of sizes 3 and 4, and whenever you need to read or write one of the integer, you'd have to std::memcpy the value. That would be a bit burdensome to implement and possibly also slower than the #pragma pack hack.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

Sadly for you, the compiler in optimising the code for a particular architecture reserves the right to pad out the structure by inserting spaces between members and even at the end of the structure.

Using a bit field does not reduce the size of the struct; you still get the whole of the "fielded" type in the struct.

The standard guarantees that the address of the first member of a struct is the same as the address of the struct, unless it's a polymorphic type.

But all is not lost: you can rely on the fact that an array of char will always be contiguous and contain no packing.

If CHAR_BIT is defined as 8 on your system (it probably is), you can model an array of 24 bit types on an array of char. If it's not 8 then even this approach will not work: I'd then suggest resorting to inline assembly.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • I don't think operating system cares about structure padding. – PcAF Jun 15 '16 at 10:10
  • _the compiler and operating system reserve the right to pad out the structure by inserting spaces between members and even at the end of the structure_ still, some compilers have the mechanism (using pragma/attribute) for packed structures. However, that applies to case of `char;int;` case. For bit-fields, it will ALWAYS allocate entire sized (INT32 in this case) variables. – anishsane Jun 15 '16 at 10:13
  • @PcAF: Indeed and have reworded a little. – Bathsheba Jun 15 '16 at 10:13