I am having some problems understanding c_ptrs in Fortran. I wrote the following program to play with c pointers. The program is very simple, to understand just go the the main program. For example, the line
call print_cptr_address(my_f_to_c_str("c_loc(ii)") , c_loc(ii))
prints the address of c_loc(ii). The line
call print_cptr_address(my_f_to_c_str("dh=c_loc(ii)") , dh)
prints the address of stored by dh , where dh=c_loc(ii), and so on.
Here is the output on my computer
c_loc(ii) : c pointer address 0x7ffe2f751228
cptr%dh=c_loc(ii) : c pointer address 0x55ea3c5050d0
cptr%dhp=>cptr%dh : c pointer address 0x55ea3c5050d0
dhp=>cptr%dhp : c pointer address 0x55ea3c5050d0
dh_copy=cptr%dh : c pointer address 0x7ffe2f751240
dh=c_loc(ii) : c pointer address 0x7ffe2f751248
I would expect the addresses would be the same but they are not. Specially the first and last output. Can someone explain me why is this?
To reproduce, copy the code and run the makefile. I compiled it with gcc 10.2.1 20210110
CODE:
makefile
all:
gcc -c test_cpart.c
gfortran -c test_fpart.F90
gfortran -o test test_cpart.o test_fpart.o
clean:
rm test_c_ptr_m.mod test_fpart.o test_cpart.o
test_cpart.c
#include <stdio.h>
#include <stdlib.h>
void print_pointer_address(char* cstr, void *ptr) {
printf("%s: c pointer address %p\n", cstr, ptr);
}
test_fpart.F90
module test_c_ptr_m
use iso_c_binding
implicit none
type :: cptr_t
type(c_ptr) :: dh = c_null_ptr
type(c_ptr), pointer :: dhp => null()
endtype
interface
subroutine print_cptr_address(cstr,ptr) bind(C, name="print_pointer_address")
use, intrinsic :: iso_c_binding
character(kind=c_char) :: cstr(*)
type(c_ptr) :: ptr
end subroutine
end interface
contains
function my_f_to_c_str(fstring) result(cstring)
character(len=*) :: fstring
character(len=:, kind=c_char), allocatable :: cstring
cstring = C_CHAR_""//fstring//C_NULL_CHAR
end function
end module test_c_ptr_m
program main
use test_c_ptr_m
use iso_c_binding
integer(c_int), target :: ii
type(cptr_t), target :: cptr
type(c_ptr), pointer :: dhp => null()
type(c_ptr) :: dh,dh_copy
ii = 500
cptr%dh = c_loc(ii)
cptr%dhp => cptr%dh
dhp => cptr%dhp
dh_copy = cptr%dh
dh = c_loc(ii)
call print_cptr_address(my_f_to_c_str("c_loc(ii)") , c_loc(ii))
call print_cptr_address(my_f_to_c_str("cptr%dh=c_loc(ii)") , cptr%dh)
call print_cptr_address(my_f_to_c_str("cptr%dhp=>cptr%dh") , cptr%dhp)
call print_cptr_address(my_f_to_c_str("dhp=>cptr%dhp") , dhp)
call print_cptr_address(my_f_to_c_str("dh_copy=cptr%dh") , dh_copy)
call print_cptr_address(my_f_to_c_str("dh=c_loc(ii)") , dh)
end program main