On a recent SO Q/A it came that the following code was not standard-conforming:
program foo
USE iso_c_binding
integer, allocatable :: a(:)
character, allocatable, target :: c(:)
integer, pointer :: p(:)
integer :: n=1000, i
a = [(i,i=1,n)]
c = transfer(a,c)
! ... then later on ...
call c_f_pointer( c_loc(c), p, [n] )
write(*,*) all(p == a) ! expected to print .true.
end program
It is non standard because for c_f_pointer
the standard requires here c
and p
to have the same type (hence being just an equivalent of p => c
), which is not the case.
C_F_POINTER(CPTR,FPRT,SHAPE)
: If the value of CPTR is the result of a reference to C_LOC with a noninteroperable effective argument X, FPTR shall be a nonpolymorphic pointer with10 the same type and type parameters as X
https://j3-fortran.org/doc/year/18/18-007r1.pdf
Yet it compiles without any warning/error with ifort and gfortran, and prints the expected result (.true.
)… which does not mean anything about the conformance.
But I wonder : how could it go wrong in practice? I cannot imagine a case where it wouldn’t work, actually.
There’s a variation of this code, using an interoperable intermediate type instead of character
:
integer(c_signed_char), allocatable, target :: c(:)
Which is still non conformant in theory, but with a different case:
C_F_POINTER(CPTR,FPRT,SHAPE)
: If the value of CPTR is the C address of an interoperable data entity, FPTR shall be a data pointer with type and type parameter values interoperable with the type of the entity.