views:

108

answers:

6

Ok i have a struct in my C++ program that is like this:

struct thestruct
{
 unsigned char var1;
 unsigned char var2;
 unsigned char var3[2];
 unsigned char var4;
 unsigned char var5[8];
 int var6;
 unsigned char var7[4];
};

When i use this struct, 3 random bytes get added before the "var6", if i delete "var5" it's still before "var6" so i know it's always before the "var6".

But if i remove the "var6" then the 3 extra bytes are gone.

If i only use a struct with a int in it, there is no extra bytes.

So there seem to be a conflict between the unsigned char and the int, how can i fix that?

+4  A: 

Are you talking about padding bytes? That's not a bug. As allowed by the C++ standard, the compiler is adding padding to keep the members aligned. This is required for some architectures, and will greatly improve performance for others.

Matthew Flaschen
+4  A: 

Your data structure being aligned so that your int falls on word boundries, which for your target might be 32 or 64 bits.
You can reorganize your struct like so so that this won't happen:

struct thestruct
{
 int var6;
 unsigned char var1;
 unsigned char var2;
 unsigned char var3[2];
 unsigned char var4;
 unsigned char var5[8];
 unsigned char var7[4];
};
fsmc
Good call on reorganizing the structure, much better than using compiler-dependent packing pragmas / attributes.
Matthieu M.
+6  A: 

The compiler is probably using its default alignment option, where members of size x are aligned on a memory boundary evenly divisible by x.

Depending on your compiler, you can affect this behaviour using a #pragma directive, for example:

#pragma pack(1)

will turn off the default alignment in Visual C++:

Specifies the value, in bytes, to be used for packing. The default value for n is 8. Valid values are 1, 2, 4, 8, and 16. The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

Note that for low-level CPU performance reasons, it is usually best to try to align your data members so that they fall on an aligned boundary. Some CPU architectures require alignment, while others (such as Intel x86) tolerate misalignment with a decrease in performance (sometimes quite significantly).

Greg Hewgill
thank you that worked
powerfear
A: 

You're having a byte alignment problem. The compiler is adding padding to align the bytes. See this wikipedia article.

nathan
A: 

Read up on data structure alignment. Essentially, depending on the compiler and compile options, you'll get alignment onto different powers-of-2.

To avoid it, move multi-byte items (int or pointers) before single-byte (signed or unsigned char) items -- although it might still be there after your last item.

NVRAM
A: 

While rearranging the order you declare data members inside your struct is fine, it should be emphasized that overriding the default alignment by using #pragmas and such is a bad idea unless you know exactly what you're doing. Depending on your compiler and architecture, attempting to access unaligned data, particularly by storing the address in a pointer and later trying to dereference it, can easily give the dreaded Bus Error or other undefined behavior.