- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Thank for any advice.
Jakub
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.
Thank for any advice.
Jakub
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash]#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; }
[/bash]
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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.
[fortran]type foo real(8) d integer(1) b end type foo type(foo) f write(*,*) sizeof(f) !gives 16[/fortran]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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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:
- Use DEC$PACK:8 in Fortran, or
- 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)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash]#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; }
[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks. So, __m128 in MSVC++ does align on 16-byte boundary, and could be used for interoperability with REAL*16.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
} quad;
I used part of definition of __m128 in xmmintrin.h
Thanks very much for suggestion.
Jakub
typedef __declspec(intrin_type) _CRT_ALIGN(16) struct{
__int64 value;
} quad;
I used part of definition of __m128 in xmmintrin.h
Thanks very much for suggestion.
Jakub

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page