mgilson
mgilson

Reputation: 309929

sizeof in fortran

It's quite common in C-code to see stuff like:

malloc(sizeof(int)*100);

which will return a pointer to a block of memory big enough to hold 100 ints. Is there any equivalent in fortran?


Use case:

I have a binary file which is opened as:

open(unit=10,file='foo.dat',access='stream',form='unformatted',status='old')

I know that the file contains "records" which consist of a header with 20 integers, 20 real numbers and 80 characters, then another N real numbers. Each file can have hundreds of records. Basically, I'd like to read or write to a particular record in this file (assuming N is a fixed constant for simplicity).

I can easily calculate the position in the file I want to write if I know the size of each data-type:

header_size = SIZEOF_INT*20 + SIZEOF_FLOAT*20 + SIZEOF_CHAR*80
data_size = N*SIZEOF_FLOAT
position = (record_num-1)*(header_size+data_size)+1

Currently I have

!Hardcoded :-(
SIZEOF_INT = 4
SIZEOF_FLOAT = 4
SIZEOF_DOUBLE = 8
SIZEOF_CHAR = 1

Is there any way to do better?

constraints:

Upvotes: 4

Views: 4503

Answers (3)

Jason
Jason

Reputation: 12283

@janneb's answer will address the OP's question, but it doesn't answer the "sizeof" question for Fortran.

A combination of inquire and file_storage_size will give the size of a type. Try this code:

program sizeof
    use iso_fortran_env
    integer :: num_file_storage_units
    integer :: num_bytes
    inquire(iolength=num_file_storage_units) 1.0D0
    num_bytes = num_file_storage_units*FILE_STORAGE_SIZE/8
    write(*,*) "double has size: ", num_bytes
end program sizeof

See: http://gcc.gnu.org/onlinedocs/gfortran/ISO_005fFORTRAN_005fENV.html http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0514.htm

Upvotes: 5

M. S. B.
M. S. B.

Reputation: 29391

If all the records are the same, this would seem to be a case to use direct access rather than stream access. Then don't calculate the position in the file, you tell the compiler the record that you want, and it accesses it. Unless you want these files to be portable across platforms or the records are not all the same ... then you have to have more control or calculate the length of the records. While the original Fortran 90 concept was to declare variables according to the required precision, there are now portable ways to declare variables by size. Either with types provided by the already mentioned iso_c_binding module, or from the iso_fortran_env module.

Upvotes: 1

janneb
janneb

Reputation: 37208

In your use case I think you could use

inquire(iolength=...) io-list

That will give you how many "file storage units" are required for the io-list. A caveat with calculating offsets in files with Fortran is that "file storage unit" need not be in bytes, and indeed I recall one quite popular compiler by default using a word (4 bytes) as the file storage unit. However, by using the iolength thing you don't need to worry about this issue.

Upvotes: 5

Related Questions