The Fortran intrinsic function transfer
can be used to covert a derived type into a real or integer array. This is potentially very useful when working in legacy systems which relies on arrays of primitive types (integer, real etc.) for persistence.
The code below runs at least on ifort
and gfortran
and converts a simple derived type example to an integer array (updated with solution):
program main
implicit none
integer, parameter :: int_mem_size = storage_size(1)
type subtype
integer a
double precision b
end type subtype
type :: mytype
integer :: foo
double precision :: bar
type(subtype) :: some_type
end type
type(mytype) :: my_var
type(subtype) :: my_subtype
! Old version: integer :: x(30)
integer, allocatable :: x(:)
integer :: mem_size
!Allocate array with required size
mem_size = storage_size(my_var)
allocate(x(mem_size/int_mem_size))
my_subtype%a = 1
my_subtype%b = 2.7
my_var%foo = 42
my_var%bar = 3.14
my_var%some_type = my_subtype
write(*,*) "transfering..."
x = transfer(my_var, x)
write(*,*) "Integer transformation:", x
end program main
On my PC, this is the output (this result is at least platform dependent):
transfering...
Integer transformation: 42 0 1610612736 1074339512
999 0 -1610612736 1074108825
My problem is that I have "guessed" that a 30 element long integer array is large enough to store this data structure. Is there a way I can determine how large the array needs to be to store the whole data structure?
If you have a Fortran 2008 compliant compiler, or one that is compliant enough, you will find the intrinsic function storage_size
which returns the number of bits used to store its argument. Failing that most compilers that I am familiar with implement a non-standard function to do this; the Intel Fortran compiler has a function called sizeof
which returns the number of bytes required to store its argument.