# Understanding gfortran's and Fortran's pass by reference nature

**URL:** <https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479>\
**Category:** Help\
**Created:** [April 2, 2023, 9:39am UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479 "2023-04-02T09:39:58Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aurelius\_Nero](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@Aurelius\_Nero](https://fortran-lang.discourse.group/u/Aurelius_Nero)\
**Post date:** [April 2, 2023, 9:39am UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/1 "2023-04-02T09:39:58Z")

</div>

Hi all,  
recently read this in the gfortran manual

> **[Argument passing conventions (The GNU Fortran Compiler)](https://gcc.gnu.org/onlinedocs/gfortran/Argument-passing-conventions.html)**
>
> Argument passing conventions (The GNU Fortran Compiler)

> GNU Fortran passes most arguments by reference, i.e. by passing a pointer to the data. Note that the compiler might use a temporary variable into which the actual argument has been copied, if required semantically (copy-in/copy-out).

Consider this module :

```auto
module addition
  use,intrinsic :: iso_fortran_env,only: real64
  implicit none
  private

  public :: add_two_numbers,add_two_numbers_using_pointers

contains

  pure function add_two_numbers(number1,number2) result(sum_of_two)
    real(kind=real64),intent(in) :: number1,number2
    real(kind=real64) :: sum_of_two

    sum_of_two = number1 + number2

  end function add_two_numbers

  pure function add_two_numbers_using_pointers(number1,number2) result(sum_of_two)
    real(kind=real64),pointer,intent(in) :: number1,number2
    real(kind=real64) :: sum_of_two

    sum_of_two = number1 + number2

  end function add_two_numbers_using_pointers

end module addition

```

and these two main programs  
main without pointers :

```auto
program main
  use,intrinsic :: iso_fortran_env,only: real64
  use addition
  implicit none

  real(kind=real64) :: data1,data2

  write(unit=*,fmt="(a,1x)",advance="no") "Please enter two numbers:"
  read *, data1,data2
  print "(a,1x,f12.6)", "The sum is:",add_two_numbers(data1, data2)

end program main

```

main with pointers :

```auto
program main
  use,intrinsic :: iso_fortran_env,only: real64
  use addition
  implicit none

  real(kind=real64),target :: data1,data2

  write(unit=*,fmt="(a,1x)",advance="no") "Please enter two numbers:"
  read *, data1,data2
  print "(a,1x,f12.6)", "The sum is:",add_two_numbers_using_pointers(data1, data2)

end program main

```

1. When I use `valgrind` on both the programs, they appear to use the same amount of memory. Why is that ?
2. In which instances are variables fully copied and not just referenced ?
3. When are pointers useful in Fortran ?

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [April 2, 2023, 7:47pm UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/2 "2023-04-02T19:47:02Z")

</div>

> [@Aurelius\_Nero](#):
>
> GNU Fortran passes most arguments by reference, i.e. by passing a pointer to the data.

This is actually rather “Everything looks like arguments are passed by reference”. The standard doesn’t require compiler to pass by reference, it just requires that everything looks like that. Compilers are free to copy-in/copy-out all arguments.

> [@Aurelius\_Nero](#):
>
> - 
> 1. When I use `valgrind` on both the programs, they appear to use the same amount of memory. Why is that ?
> 
> - 
> 1. In which instances are variables fully copied and not just referenced ?
> 
> - 
> 1. When are pointers useful in Fortran ?

1. Why would you expect something else?
2. Just looking at this code, you cannot tell. In both cases the compiler can pass the arguments by reference, but it is also free to pass them by copy-in/copy-out
3. Since allocatables have been allowed in derived types and for dummy arguments, pointers are not often needed. Still there are some usages, e.g. linked lists.

Keep also in my that a Fortran pointer is a quite different thing than a C pointer.

---

<div class="post-metadata">

**Author:** ![Aurelius\_Nero](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@Aurelius\_Nero](https://fortran-lang.discourse.group/u/Aurelius_Nero)\
**Post date:** [April 2, 2023, 8:44pm UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/3 "2023-04-02T20:44:20Z")

</div>

> [@PierU](#):
>
> Why would you expect something else?

I was under the naive impression that pointers would help lower memory usage since they only contain the memory address and not the value itself.

> [@PierU](#):
>
> Keep also in my that a Fortran pointer is a quite different thing than a C pointer.

Could I trouble you to explain the differences to me please, or give me a link. 🙏

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [April 3, 2023, 2:54am UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/4 "2023-04-03T02:54:39Z")

</div>

> [@Aurelius\_Nero](#):
>
> I was under the naive impression that pointers would help lower memory usage since they only contain the memory address and not the value itself.

First, as already pointed out, a fortran pointer is not simply an address. There is also rank, size, and bound information in the metadata.

Second, your statement might have been true when addresses were 16-bits and pointed to 32-bit or 64-bit data. On modern architectures, addresses are usually 64-bit entities, so the address itself often takes more memory than the data to which it points.

---

<div class="post-metadata">

**Author:** ![Aurelius\_Nero](https://avatars.discourse-cdn.com/v4/letter/a/a87d85/32.png) [@Aurelius\_Nero](https://fortran-lang.discourse.group/u/Aurelius_Nero)\
**Post date:** [April 3, 2023, 8:10am UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/5 "2023-04-03T08:10:01Z")

</div>

@PierU and @RonShepard Thank you two for the answers.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [April 3, 2023, 9:59am UTC](https://fortran-lang.discourse.group/t/understanding-gfortrans-and-fortrans-pass-by-reference-nature/5479/6 "2023-04-03T09:59:01Z")

</div>

> [@Aurelius\_Nero](#):
>
> I was under the naive impression that pointers would help lower memory usage since they only contain the memory address and not the value itself.

Even if they were containing only an address, the actual values have to be actually stored. So at best the pointer version of the program requires the same amount of memory.

> [@Aurelius\_Nero](#):
>
> Could I trouble you to explain the differences to me please, or give me a link. 🙏

As previously written, a Fortran pointer contains the whole description of the pointed object, not only its address. In that sense, Fortran pointers are strongly typed. C pointers are also typed, but to a lesser extent (being essentially an address, a C pointer can be easily casted to any other pointer, whatever the type).

Another difference is that one can never access the address of a Fortran pointer: if you try to do so, you get the address of the pointed object. See this code (`loc()` is not a standard function, but in practice many compilers have it to get the address of an object):

```auto
integer, target :: a
integer, pointer :: b
b => a
write(*,*) loc(a), loc(b)

```

which outputs the same address for `b` and `a`:  
` 4769164 4769164`

The “equivalent” C code does output 2 different values:

```auto
    int a;
    int* b;
    b = &a;
    printf("%p %p\n",&a,&b);

```

output:

```auto
 0x7fffef5cf56c 0x7fffef5cf560

```
