Ezio
Ezio

Reputation: 1175

Why the same structure's size is calculated different in X86 and arm with the similar version gcc?

As subject says, I got different result of the same operation that calculate a same structure. The struct is below.

struct test
{
  char m1;
  double d1;
}

When use sizeof(struct test) calculate it in gcc-4.6.3 and gcc-4.2 in linux, I got the result "12". While I use gcc-4.6.1 in linux and VC 6.0 in WinXP, I got the result "16". So I'm confused, why this happen? How GCC calculate a struct's size?

added:

as the answers say,arm linux require 8-byte alignment for AAPCS defines,but why vc 6.0 in x86 get the result "16"?Does anyone use vc 2003 or later calculate this?

what's more does C standard such as C89/C99 define this?

Upvotes: 1

Views: 2621

Answers (2)

artless-noise-bye-due2AI
artless-noise-bye-due2AI

Reputation: 22430

To supplement Dave-B's answer,

The gcc changes include a note on an ABI change to align vectors larger than 8 bytes on an 8 byte boundary. Table 4.1 of the ARM AAPCS give alignment documentation,

Procedure Call Standard for the ARM Architecture
4.1 Fundamental Data Types
Type     Class       Byte size Byte alignment
Integral Unsigned    8             8
             double-word
Floating Double       8             8
Point     Precision

This is generally advantageous as the data will not straddle a cache line. Also, the ARM ldrd and strd are faster if the memory is aligned. As this is part of the ARM standard for C compiler inter-operability gcc should do this by default. Using attribute(packed) and optimizing for size -Os may change the alignment.

An internal bus used on many ARM processors is 64bit.

See also: ARM C calling convention

Upvotes: 2

Dave B
Dave B

Reputation: 186

A double is always 8 bytes long, but the alignment requirements differ based on the architecture. In ARM (apparently, from your example) the requirement is to align doubles on an 8 byte boundary.

Structures are always padded with space to make their size a multiple of the field with the largest alignment requirement. In the example above, the compiler will put m1, then 3 (or 7) bytes of padding, then d1.

Just to be confusing, on x86 the alignment only NEEDS to be a 4-byte boundary, but GCC can optionally make it an 8 byte boundary for performance. From the gcc man page:

-malign-double

-mno-align-double

Control whether GCC aligns double, long double, and long long variables on a two word boundary or a one word boundary. Aligning double variables on a two word boundary will produce code that runs somewhat faster on a `Pentium' at the expense of more memory. Warning: if you use the -malign-double switch, structures containing the above types will be aligned differently than the published application binary interface specifications for the 386 and will not be binary compatible with structures in code compiled without that switch.

Upvotes: 6

Related Questions