Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs have moved to the Altera Community. Existing Intel Community members can sign in with their current credentials.
29308 Discussions

Are data structures always contiguous?

schulzey
New Contributor I
1,236 Views

Does anyone know if a data structure such as the one below is always contiguous in memory? I can't quite tell from the documentation.

STRUCTURE /Fred/
   INTEGER*4  IntArray(10)
   REAL*8  FltArray(23)
   CHARACTER  String*100
   INTEGER*4  Flag
END STRUCTURE

RECORD /Fred/ MyStructure(12)

I have tried adding the CONTIGUOUS attribute to my declaration but the compiler doesn't like it and so I am assuming that it is always contiguous.

0 Kudos
7 Replies
TimP
Honored Contributor III
1,236 Views

If the compiler doesn't like contiguous here, I would assume it's because it's unable to avoid padding, or because you have a conflict between legacy non-standard extensions and later standard features.

I think it would be reasonable to interpret the ABI requirements such that both the integer and real*8 arrays must be 16-byte aligned.   I wouldn't be surprised if the documentation doesn't cover this mixture of non-standard syntax.

0 Kudos
Steven_L_Intel1
Employee
1,236 Views

First of all, the CONTIGUOUS attribute does not instruct the compiler to make something contiguous. Rather, it is used on pointers and assumed-shape dummy arguments to promise the compiler that the object is indeed contiguous. It is not applicable to your case.

The compiler may or may not insert padding into that structure depending on compiler options and other directives in the source. The default is to not insert padding. My advice would be to use the Fortran 2003 TYPE declaration with BIND(C) - that will specify the exact layout, rather than relying on extensions and default behaviors.

0 Kudos
dboggs
New Contributor I
1,236 Views

Have you tried using a derived type instead of a structure? The documentation tells me that CONTIGUOUS works with a derived type, while it says nothing about use with a structure.

Note that a derived type is simply the "official" modern incarnation of the structure, which was a vender-dependent extension used with Fortran 77. Intel still maintains it for compatibility (Intel people, please correct me if I'm wrong on this).

0 Kudos
schulzey
New Contributor I
1,236 Views

I need the data structure to be contiguous because I like to use the ZeroMemory Windows API to initialize it at various locations in my code just before I reload parts of it with data using something like the following:

CALL ZeroMemory(loc(MyStructure), SizeOf(MyStructure))
Load selected variables of MyStructure with data... 

I use ZeroMemory so that I don't have to set every element of the data structure to NULL individually. If the data structure is not contiguous then I am assuming that ZeroMemory would cause problems.

I am gradually converting my STRUCTURE declarations to TYPE declarations, however I assumed that my contiguous question would apply equally to them also.

If I use a STRUCTURE or TYPE declaration and do nothing else to it, is it contiguous in memory? Note that I am using the /align:rec1byte to remove padding for other reasons.

 

0 Kudos
IanH
Honored Contributor III
1,236 Views

In the absence of allocatable or pointer components (and perhaps one day length type parameters), and if the array being declared is not a pointer or assumed shape dummy argument - yes, practically.  More so even, if the type is a sequence type.

Note that zeroing the memory of a character component isn't the same as assigning a zero length string to the component.

If someone does pop an allocatable component into the type one day, then the ZeroMemory approach is going to cause serious runtime issues.

Are you familiar with default initialization?  When combined with structure constructors that would let you achieve better brevity and clarity of source at the point of use, without needing to use extensions to the standard.

[fortran]PROGRAM UnderConstruction
  IMPLICIT NONE
 
  TYPE Fred
    INTEGER :: IntArray(10) = 0
    REAL :: FltArray(23) = 0.0
    CHARACTER(100) :: String = ''
    INTEGER :: Flag = 0
  END TYPE Fred
 
  TYPE(Fred) :: a
  TYPE(Fred) :: b(5)
 
  a = Fred()
  a%IntArray(2) = 10
  PRINT "('After setting to some value: ',*(I0,:,1X))", a%IntArray
 
  a = Fred()
  PRINT "('After (re)construction: ',*(I0,:,1X))", a%IntArray
 
  b = Fred(Flag=1)    ! All b's have a Flag of 1.
  b(2)%Flag = 9       ! Now element 2 is special.
  PRINT "('After setting to some value: ',*(I0,:,1X))", b%Flag
 
  b = Fred()
  PRINT "('After (re)construction: ',*(I0,:,1X))", b%Flag
END PROGRAM UnderConstruction[/fortran]

0 Kudos
Steven_L_Intel1
Employee
1,236 Views

CONTIGUOUS simply means that there is no spacing between array elements. It has no effect on layout of a structure or derived type. It is applicable only to an array pointer or assumed-shape array.

BIND(C) for a derived type is better than SEQUENCE here. SEQUENCE simply prevents the compiler from rearranging components, not that Intel Fortran does that. It doesn't necessarily prevent padding, though by default we won't pad a SEQUENCE type. BIND(C) types are better in that the standard specifies what the layout should be, though if the "companion C processor" would add padding, so would Fortran.

We do have directives such as !DIR$ OPTIONS /NOALIGN that can be used to disable alignment padding no matter what compiler options were specified.

0 Kudos
schulzey
New Contributor I
1,236 Views

Thanks, that clarifies it.

My problem is that I need to maintain my source code for an old Watcom Fortran compiler as well as the latest Intel one, and I'm trying to avoid having thousands of #ifdef's as much as possible. It should be smooth sailing once I've weened off the old compiler.

0 Kudos
Reply