# Data alignment problem - size of derived type

## Data alignment problem - size of derived type

I have complex data structure (see attached project).

When I run my test code I obtain following results:
size of structure 2224 bytes
position of last element 2208 bytes
size of last element 4 bytes
assumed size 2212 bytes

So there is discrepancy between size of structure 2224 (given by sizeof) and assumed size of structure 2212 calculated from position of last element and its size.

Because 2212 cannot be divided by 8 I expect size of structure to be 2216 bytes. When I use the same structure rewriten to C++ I obtain size of structure 2216 bytes.

So my question is where are another 8 bytes which FORTRAN allocates for structure.

I am using 11.1.67 fortran on Windows.

Jakub

AttachmentSize
2.59 KB
7 posts / 0 new
For more complete information about compiler optimizations, see our Optimization Notice.

With natural alignment in effect, sizeof a structure (in both Fortran and C++) is always a multiply of its largest basic element. That ensures correct alignment within arrays of such structures. Consider:

```type foo
real(8) d
integer(1) b
end type foo
type(foo) f
write(*,*) sizeof(f) !gives 16```

If you had an array of 2 foos (aligned at 8-byte boundary), sizeof=16 ensures that the second member will also be aligned so that d begins at an 8-byte boundary. That means that you would have "wasted" 7 bytes between first and second element.

In your case, the largest element is real*16, and 2224 is divisible by 16; you have 2224-2212=12 unused bytes at the end.

That rule is the same in both C and Fortran. I cannot tell where your C/Fortran discrepancy comes from. Since 2216 is divisible by 8, I will guess that the default packing in your C compiler is #pragma pack(8), while in Fortran it is !DEC\$PACK:16. (I have never encountered 16-byte reals, so I don't know how compilers behave in their presence). If I'm right, some of your real*16 would be misaligned in C. Make sure the compilers use the same packing, and you'll be good to go.

Jugoslav www.xeffort.com

After having peeked into the code, I think that the issue comes because real*16 is a "native" Fortran type, while Microsoft C/C++ only implements it as a struct (according to this, Intel C++ compiler does recognize the quad-precision real). Thus, visual C does not "feel the need" to align it at 16-byte boundary, and does not "obey" pragma pack(16). I don't think that there is a 16-byte basic entity, so that you could use it instead of struct.

Not sure what to suggest, because I'm not familiar with how the REAL*16 is implemented, and how sensitive to misalignment it is. Two immediate solutions come to my mind, none particularly appealing:

1. Use DEC\$PACK:8 in Fortran, or
2. Fill the end of the appropriate C++ struct with 12 bytes of unused padding. That will give you correct alignment, but could be painful to maintain if you expand the code. By "appropriate", I mean the one which actually needs the padding (didn't check your code carefully to tell you exactly)
Jugoslav www.xeffort.com

Thanks Yugoslav,
I will use some junk variables at the end of the data structure and will keep on mind to check it when structure changes.

Jakub

```#include
#include

struct twoXeight
{
double x;
double y;
};

struct test
{
union
{
__m128 m128test;
struct twoXeight goodstuff;
};
char c;
};

int main()
{
struct test t;
printf("%dn", sizeof(t));
t.goodstuff.x = 1;
t.goodstuff.y = 2;
t.c = '3';
printf("%f %f %cn", t.goodstuff.x, t.goodstuff.y, t.c);
return 0;
}

```

Thanks. So, __m128 in MSVC++ does align on 16-byte boundary, and could be used for interoperability with REAL*16.

Jugoslav www.xeffort.com

According to previous answer I succeeded with following definition of real*16 in C++ (it have the same properties in structures as real*16, but of course does not display correct real*16 value, only creates space for it)

typedef __declspec(intrin_type) _CRT_ALIGN(16) struct{
__int64 value;