4

The scope is in x86
For example, we have a struct like this:

struct X{
   int    a;   
   char   b; 
               // compiler will pad 3 bytes here
   double c;
};
X x;

I think the alignment of x should be the largest member in it, in this case is double, which is 8 bytes,
so &x should be a multiple of 8, am I right?

However, after some tests, my compiler(msvc 2013) says &x can also be a multiple of 4 but not 8.

Isn't it meaning &x.c will also be a multiple of 4?

Where do I misunderstand?

user3439246
  • 43
  • 1
  • 5
  • 2
    It's compiler-dependent. See for example http://stackoverflow.com/questions/5397447/struct-padding-in-c – Nathan Monteleone Mar 19 '14 at 20:03
  • I'd be very interested to see a number other than four that's a multiple of four, but not eight. Joking aside, while you can't rely on much in terms of cross-platform compatibility, your system very probably _does_ specify this sort of thing or adhere to a specification. The [System V specification for x86](http://math-atlas.sourceforge.net/devel/assembly/abi386-4.pdf), for example, specifies `double` to be aligned to four bytes, not eight. – Stuart Olsen Mar 20 '14 at 01:05

3 Answers3

3

The C and C++ standards does not give any advice [or at least no firm rules] on what alignment should be. It is up to each compiler (and of course, what target the compiler is for) to determine a good policy. It's often preferred if this policy works for the target... ;)

Since the FPU [including SSE in scalar mode] of x86 can read "double" from any byte-address and I believe there is no direct benefit in adding more than 3 bytes between the b and c elements, nor to align the whole struct to anything more than 4 bytes. Doing more would waste memory.

In some other architecture, it may well be a great benefit (or a requirement for the target to operate correctly), and it would thus align the whole struct to 8 bytes.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
2

Structure alignment in VC is a compiler option /Zp determines the byte boundaries on which your structures will be packed. This is normally an advanced option and not used except in unusual use cases (such as doing a memcpy of block data for transfer over the network). Check the property pages of the project in order to see what the alignment is.

http://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx

edtheprogrammerguy
  • 5,957
  • 6
  • 28
  • 47
1

Generally speaking you can't say that much about the size, the alignment or how your struct is packed, and by "generally" I mean according to the C++ standard of your choice.

The problems are:

  • int, char and double have no defined size according to the standard, the standard simply sets some minimum requirements, what you are going to get depends on the implementation
  • alignment depends not only on the compiler implementation but sometimes even on the set of flags that you are passing and what hardware you are targeting, packing is extremely important for the CPU cache and some instructions may even need different padding, this also depends on what you are putting in the struct and how you are writing it.

As a consequence for this kind of operations you have to literally stick with the documentation of the compiler of your choice and dive into the features that it provides you, for example here you can find an overview on how to pack data in gcc vs msvc .

Community
  • 1
  • 1
user2485710
  • 9,451
  • 13
  • 58
  • 102
  • No what. It is by definition 1. Please look at the link I have provided under notes. – Jan Herrmann Mar 19 '14 at 20:26
  • @JanHerrmann from the link that you are posting: "Depending on the computer architecture, a byte may consist of 8 or more bits", again, now tell us how big are those 3 types according to the C++ standard. And not in terms of bytes, in terms of bits and alignment, if you can do that you win. – user2485710 Mar 19 '14 at 20:28
  • according to the link I provided `sizeof` is defined in the standard for `char`, `signed char` and `unsigned char` to return 1. And alignof (http://en.cppreference.com/w/cpp/language/alignof) returns the smallest allignment. The size of `int` and `double` are implementation defined but not the size of `char`. So your first point is not correct. – Jan Herrmann Mar 19 '14 at 20:36
  • @JanHerrmann re-read again, you are wrong, the sizeof operator returns bytes, even if you know that a thing is 1 byte but you can't define how much is a byte, you know nothing about the size of the type, it's as simple as that. – user2485710 Mar 19 '14 at 20:38
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/50071/discussion-between-jan-herrmann-and-user2485710) – Jan Herrmann Mar 19 '14 at 20:40