Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28621 Discussions

Unformatted write of derived type which is not aligned

AONym
New Contributor II
622 Views

From another source, I am receiving binary files in which the fields are not aligned. I am reading these files under C++, using a C++ struct which is "packed", like this:

#pragma pack(push,1)
struct Unaligned
{
char c;
int i;
};

In C++, "pack" means the fields of the struct occupy successive bytes, with no padding added for alignment.

In Fortran, I need to write a file in the same format. I cannot find anything analogous to the C++ `pragma pack`. I did find a post by Steve Lionel from 2017, in response to a similar question:

"...components do get padding for natural alignment by default in Intel Fortran. You can disable this by 1) Making the type a BIND(C) type, 2) Specifying /noalign when compiling, 3) bracket the type declaration with !DIR$ OPTIONS /NOALIGN ... !DIR$ END OPTIONS, 4) Make the type a SEQUENCE type (not recommended)"

In Fortran, I have, for example,

TYPE, BIND(C) :: Unaligned
    INTEGER(C_CHAR) :: c
    INTEGER(C_INT) :: i
END TYPE Unaligned
TYPE(Unaligned), TARGET :: hdr ! TARGET allows a pointer, for debugging

I am opening an output file with

OPEN(UNIT = ioXLI, FILE = TRIM(path), FORM = 'unformatted', ACCESS = 'stream', status = 'replace')

and writing my unaligned derived type with

WRITE(ioXLI, IOSTAT = status) hdr

Now I have two problems: (1) the Fortran derived padding added; and (2) the output file has what I presume is a 4-byte record length written before the values in `hdr`, which cannot be in the output. I need to solve both of these to produce an output file in the correct format.

Windows 11, Visual Studio 2022 17.6.5,  Intel Fortran (ifort) 2023.2.

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
449 Views

Note that SEQUENCE promises only not to reorder the components - it says nothing about packing. Whether a compiler packs SEQUENCE types or not is implementation-dependent.

View solution in original post

3 Replies
AONym
New Contributor II
584 Views

I have solved both problems.

The Fortran type is "packed" when I both make the type a BIND(C) type AND bracket the type declaration with !DIR$ OPTIONS /NOALIGN ... !DIR$ END OPTIONS (Steve Lionel's suggestions).

The output file format from

 

OPEN(UNIT = ioXLI, FILE = TRIM(path), FORM = 'unformatted', ACCESS = 'stream', status = 'replace')

 

inserts unwanted 4-byte "record lengths", but

 

OPEN(UNIT = ioXLI, FILE = TRIM(path), FORM = 'binary', ACCESS = 'stream', status = 'replace')

 

does not. In other words, the FORM = 'binary' causes an unformatted write to behave like a C++ stream, as desired.

jimdempseyatthecove
Honored Contributor III
548 Views

There is also SEQUENCE.

Jim

0 Kudos
Steve_Lionel
Honored Contributor III
450 Views

Note that SEQUENCE promises only not to reorder the components - it says nothing about packing. Whether a compiler packs SEQUENCE types or not is implementation-dependent.

Reply