laserbrain
laserbrain

Reputation: 1045

Pointer casting in Fortran

For interoperability with the C programming language I need to cast a pointer in Fortran. Essentially, I like to achieve in Fortran what looks the following in C:

#include <stdio.h>

int main(int argc, char **argv)
{
    int  n = 100;
    long ptr;

    ptr = (long) &n;
    printf("ptr: %ld\n", ptr);
} 

(long used for simplicity here, int_ptr_t should be preferred.) The example outputs:

ptr: 140737488349460

But trying the same in Fortran using transfer() leads to something different:

program main
    implicit none
    integer, target :: n = 100
    integer(kind=8) :: ptr

    ptr = transfer(loc(n), ptr)
    print '(a, i0)', 'ptr: ', ptr
end program main

Output:

ptr: 6296120

One could also use the appropriate ISO C binding types and functions, with the very same result:

program main
    use, intrinsic :: iso_c_binding
    implicit none
    integer(kind=c_int), target :: n = 100
    integer(kind=c_intptr_t)    :: ptr

    ptr = transfer(c_loc(n), ptr)
    print '(a, i0)', 'ptr: ', ptr
end program main

Why is loc(n)/c_loc(n) not returning a similiar memory address?

(Examples have been compiled with GCC 9 and GNU Fortran 9.)

Upvotes: 0

Views: 1050

Answers (1)

laserbrain
laserbrain

Reputation: 1045

Fortran only stores allocatable variables on the stack. Therefore, the variable of which the stack address is wanted must be declared as pointer or allocatable:

program main
    use, intrinsic :: iso_c_binding
    implicit none
    integer(kind=c_int), pointer :: n => null()
    integer(kind=c_intptr_t)     :: ptr

    allocate (n)
    n = 100
    ptr = transfer(c_loc(n), ptr)
    print '(a, i0)', 'ptr: ', ptr
end program main

Result:

ptr: 34366292000

Upvotes: 1

Related Questions