Unexpected `shape` of array pointer

In preparing a minimal working example for a pointer-related question, I found that a pointer to multi-dimensional arrays behaved in a way I did not expect. In the program below, I have two-multidimensional arrays a and b, with the rank of b being one less than that of a. I am trying to use a pointer c to represent the “concatenation” of a and b along one dimension. However, I must misunderstand something about pointer semantics, because this does not seem to be what happens.

  implicit none

  integer, parameter :: k = 40, l = 30, m = 20, n = 10

  real, target, allocatable :: a(:,:,:,:), b(:,:,:)
  real, pointer :: c(:,:,:,:)

  allocate (a(k,l,m,n), b(k,m,n))
  allocate (c(k,l+1,m,n))

  call random_number(a)
  call random_number(b)

  c(1:k,1:l,1:m,1:n) => a
  print *, shape(c) ! 40 30 20 10 -- expected 40 31 20 10

  c(1:k,l+1:l+1,1:m,1:n) => b
  print *, shape(c) ! 40 1 20 10 -- expected 40 31 20 10
end

For completeness, this program compiled and executed without warning using gfortran 9.2.0 with the options “-std=f2018 -Wall -Wextra”. Is this how pointers are meant to work? I’d appreciate if anyone can shed some light on this. I think @arjen was recently looking into something similar having to do the concatenation operator in mathematics of arrays.

Yes.

It appears your “expected” values are based on your ALLOCATE statement toward c (line #9). However that allocation has no bearing on the targets of c in subsequent pointer assignments. And the resulting SHAPE of c'.

Separately, you will note that allocation of c is of no use, a conforming processor is not required to do garbage-collect the memory allocated there with an anonymous target. So that there can be a memory leak even as there is no way of referencing that target following those pointer assignments involving c.

1 Like

To put it in another way: a pointer variable like c will point to a single piece of memory, it cannot simultaneously hold a pointer to another piece of memory. It can reshape the memory and it can use strides other than 1, but that all refers to the same piece. The catenation operation cannot be implemented in this way, unfortunately. Which is why my implementation is a bit more complicated and diverges from a simple array-type interface

1 Like

I see, thanks both @FortranFan and @Arjen for the explanations.

I had the brief thought that maybe equivalence could be used to achieve the intended effect, but I think it has a similar constraint of not being able to reference different areas of memory.