sizeof() not working ?!?

Started by
19 comments, last by Trienco 11 years, 2 months ago

Hi guys, I am having a hard time understanding something right now:


struct FormatChunk
{
 BYTE subchunk1ID[4];
 DWORD subchunk1Size;
 short audioFormat;
};
 
DWORD dwSize=sizeof(FormatChunk); // is 12  !!!!
dwSize=sizeof(short); // is 2 like it should be

What the hell ?

Advertisement
You have 4 BYTEs, a DWORD (4 more bytes) and a short (2 bytes). Including structure padding, this gives 12 bytes.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

What you're seeing is data alignment at work. Basically your DWORD needs to be allocated on a multiple of four bytes, so the size of the struct needs to be a multiple of four bytes.
structs are usually padded to a 4 byte boundary. If you are using MSVC, you can control the packing, check out #pragma pack. If you can afford the memory, go with the usual packing though (it's more efficient to read DWORDs off 4 byte boundaries usually). Packing is important if you are worried about data file size or sending it acros a network, however.
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Ahh, ok guys, I thought I was going crazy.

I'm going to read up on it.

In general though, if I have to read 10 bytes into that struct I can't rely on sizeof() and should explicitly set it to read 10, is that right ?

Thanks.

If your structure is meant to be used to map in-memory file data you should enforce finer control over the alignment/padding of the structure with #pragma pack where available.

If not available, you should approach the problem in a different way period.

If your byte array was 3 bytes instead of 4 bytes in length, subchunk1Size would still be aligned to 4 bytes, with an extra byte added before it for padding.

Padding does not occur just at the end of structures, but also between members inside the structure, so if you can’t strictly control how it is padded, don’t even try to use that approach.

So no, don’t hard-code 10 anywhere. You should use sizeof(), and if that is not reliable then don’t use this method at all.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Nope, if you save it out use sizeof(FormatChunk) to get how many bytes to write out (and read in). Never manually try and work out the size of a struct to write to disk.
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Your safest option is to read and write each element individually.

sizeof(subchunk1ID) + sizeof(subchunk1Size) + sizeof(audioFormat) will always be 10 regardless of any structure padding.

Yikes, that's a maintenance nightmare if you add a field to the struct or change the order of them.
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

The best option is typically to use #pragma pack (with push/pop). This allows you to eliminate the padding entirely (using a pack of 1), and at that point the representation in memory should be identical to that on disk (barring endian issues, which you are far less likely to run into since Mac's switched to Intel).

However, be aware that there is a performance penalty to read/write unaligned memory - you should only pack structures directly involved in I/O.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement