Pointing to a scalar

I ran into a peculiar limitation:

You can have a three-dimensional pointer point to a one-dimensional array, but you cannot do so with a scalar. The compilers I used complain about the target not being a rank-1 array and not being simply contiguous. But how can a scalar NOT be contiguous?

It is illustrated by a program as simple as this one:

program show_ptr
    implicit none

    real, target                  :: x
    real, dimension(:), pointer   :: y

    x = 1.0
    y(1:1) => x
    write(*,*) y, size(y), shape(y)
end program show_ptr

I have to accept the limitation, but I would like to know the rationale :slight_smile:

In many languages a pointer points to an address. This is very flexible, but also very error-prone. In Fortran a pointer has attributes such as rank and type that must match whatever it is pointing to, and targets must be explicitly designated as such. This is a very different, much more restrictive definition of a pointer that avoids many of the common errors generated by the simple address pointers but can take some getting used to. I think that you will find that pointers are rarely needed in Fortran and are generally best avoided except in rare cases, as perhaps in several (common) specific cases – linked lists first come to mind.

Don’t use them out of habit if you come at Fortran from something like a C programming background. In Fortran they should be treated more as a necessary evil than as a principal method.

Fortran (perhaps more than any other language(?)) has quite a few restrictions specifically to help prevent coding errors that sometimes feel limiting but are basically a compromise between not allowing a feature at all or allowing it, but in as safe a manner as possible. Fortran pointers certainly fall into that category.

To truly understand Fortran pointers you also need to understand that bounds are applied to them as well. You can’t simply start striding through memory based off their values. If you understand this example you are well on your way to understanding Fortran pointers. They probably should have been given a different name, as the term “pointer” carries a lot of baggage for anyone familiar with them as commonly implemented in other languages.

Forget everything you know about pointers from other languages when working with Fortran pointers and treat them as a new paradigm is my advice.

program show_ptr
implicit none
real, target                  :: x
real, dimension(:), pointer   :: y
real, dimension(3), target    :: z
real, pointer :: a, b, c
    z=[10.0,20.0,30.0]

    x = 1.0
    a=>z(1)
    b=>z(2)
    c=>z(3)
    !NO!y(1:1) => z(3)  
    y(20:20) => z(3:3)
    write(*,*) y, size(y), shape(y),lbound(y),ubound(y)
    y(30:30) => z(2:2)
    write(*,*) y, size(y), shape(y),lbound(y),ubound(y)
    !NO!y(3:1:-1)=>z
    y=>z
    y(1:3)=>z
    write(*,*) y, size(y), shape(y),lbound(y),ubound(y)
    write(*,*)a,b,c
end program show_ptr
2 Likes

Be assured that I understand them :slight_smile: (or at least can claim so) and I definitely appreciate the more encompassing notion of a pointer in Fortran (even though I generally avoid them). The question arose in a context where the library deals with arrays of sorts and the question was if via a “cast” to a array pointer it could be expanded to include scalars. A second situation is in the mathematics of arrays discussion/project (see the discussion by that title). Here the catenation operation juxtaposes two arrays and it would be nice if you could juxtapose an array and a scalar as well, using the technique of associating an array pointer to a scalar.
(On stackoverflow a workaround was presented which uses c_f_pointer)

1 Like

I missed that it was a nuanced question! That clarified that a lot. The general issue that a pointer in Fortran has attributes causes a lot of initial confusion. Yes, in the case of a regular value an assignment is making a copy of the value (like in arr(1)=x) but the Fortran pointer insists on just pointing to something with the same attributes that are already defined so you could not even create a function that when passed a scalar returned an array pointer to get what you want.

I think that the notion of a pointer variable in Fortran can be confusing to someone who comes to Fortran after learning and using pointers in C. Someone once pointed out that in C you can point at anything and then take the consequences, whereas in Fortran you can only point at a willing victim (a variable with the TARGET or POINTER attribute). The other stumbling block is that there is no dereferencing operator in Fortran, whereas in C there is: ‘*’.

Fortunately, ever since ALLOCATABLE variables became available and can be passed as arguments, we do not need to struggle with pointers as much as we had to do in Fortran 90.

My take on a rationale… You certainly CAN have a pointer to a scalar. What you can’t do is use pointer bounds remapping (what Arjen was trying) to point to a scalar. The idea of bounds remapping is to provide a different view of the same array. For a scalar data-target, you’d be restricted to specifying an extent of 1 in the remapping, which seems silly. Allowing a scalar data-target would complicate the text in the standard for not much usefulness.

1 Like

Okay, I can imagine that :slight_smile: My use case is pretty specific and I can probably use the workaround via c_f_pointer (it would be entirely isolated, so little chance of falling into the general pitfalls of pointing to anything).