Spec-Zone.ru › GNU Fortran 13

5.1.16 Указатели Cray

Указатели Cray являются частью нестандартного расширения, предоставляющего указатель в стиле C для Fortran. Это достигается с помощью пары переменных: целого «указателя», который хранит адрес памяти, и «указанного», используемого для разыменования указателя.

Пары указатель/указанный объявляются в операторах вида:

pointer ( <pointer> , <pointee> )

или,

pointer ( <pointer1> , <pointee1> ), ( <pointer2> , <pointee2> ), ...

Указатель — это целое число, предназначенное для хранения адреса памяти. Указанный может быть массивом или скаляром. Если массив с предполагаемым размером разрешен в области видимости, указанный может быть массивом с предполагаемым размером. То есть, последняя размерность может быть оставлена неопределенной, используя * вместо значения. Указанный не может быть массивом с предполагаемой формой.

Тип указанного может быть объявлен до или после оператора указателя, а его спецификация массива (если она есть) может быть объявлена до, во время или после оператора указателя. Указатель может быть объявлен как целое число до оператора указателя. Однако некоторые машины имеют размеры целых чисел по умолчанию, которые отличаются от размера указателя, и поэтому следующий код не является переносимым:

integer ipt
pointer (ipt, iarr)

Если указатель объявлен с типом, который слишком мал, компилятор выдаст предупреждение; полученный двоичный файл, вероятно, не будет работать правильно, поскольку адреса памяти, хранящиеся в указателях, могут быть усечены. Безопаснее опустить первую строку приведенного выше примера; если явное объявление типа ipt опущено, компилятор гарантирует, что ipt является целочисленной переменной, достаточно большой для хранения указателя.

Арифметика указателей допустима с указателями Cray, но она не такая же, как арифметика указателей C. Указатели Cray — это просто обычные целые числа, поэтому пользователь отвечает за определение того, сколько байтов нужно добавить к указателю для его инкремента. Рассмотрим следующий пример:

real target(10)
real pointee(10)
pointer (ipt, pointee)
ipt = loc (target)
ipt = ipt + 1

Последнее утверждение не устанавливает ipt в адрес target(1), как это было бы в арифметике указателей C. Добавление 1 к ipt просто добавляет один байт к адресу, хранящемуся в ipt.

Любое выражение, включающее указанный, будет переведено с использованием значения, хранящегося в указателе, в качестве базового адреса.

Для получения адресов элементов это расширение предоставляет встроенную функцию LOC(). Функция LOC() эквивалентна оператору & в C, за исключением того, что адрес преобразуется к целочисленному типу:

real ar(10)
pointer(ipt, arpte(10))
real arpte
ipt = loc(ar)  ! Makes arpte is an alias for ar
arpte(1) = 1.0 ! Sets ar(1) to 1.0

Указатель также можно установить с помощью вызова встроенной функции MALLOC (см. MALLOC — Выделить динамическую память).

Указанные Cray часто используются для алиасирования существующей переменной. Например:

integer target(10)
integer iarr(10)
pointer (ipt, iarr)
ipt = loc(target)

Пока ipt остается неизменным, iarr теперь является алиасом для target. Однако оптимизатор не обнаружит этот алиасинг, поэтому небезопасно использовать iarr и target одновременно. Использование указанного каким-либо образом, нарушающим правила или предположения Fortran об алиасинге, является недопустимым. Пользователь несет ответственность за предотвращение этого; компилятор работает под предположением, что такого алиасинга не происходит.

Указатели Cray будут работать правильно, когда нет алиасинга (т.е., когда они используются для доступа к динамически выделенному блоку памяти), а также в любой процедуре, где используется указанный, но любая переменная, с которой он разделяет хранение, не используется. Код, который нарушает эти правила, может не работать так, как предполагает пользователь. Это не ошибка оптимизатора; любой код, нарушающий правила алиасинга, является недопустимым. (Обратите внимание, что это не уникально для GNU Fortran; любой компилятор Fortran, поддерживающий указатели Cray, «неправильно» оптимизирует код с некорректным алиасингом.)

Существует ряд ограничений на атрибуты, которые могут быть применены к указателям и указанным Cray. Указанные не могут иметь атрибуты ALLOCATABLE, INTENT, OPTIONAL, DUMMY, TARGET, INTRINSIC, или POINTER. Указатели не могут иметь атрибуты DIMENSION, POINTER, TARGET, ALLOCATABLE, EXTERNAL, или INTRINSIC, а также не могут быть результатами функций. Указанные не могут встречаться более чем в одном операторе указателя. Указанный не может быть указателем. Указанные не могут встречаться в операторах эквивалентности, общего использования или данных.

Указатель Cray также может указывать на функцию или подпрограмму. Например, следующий фрагмент является допустимым:

implicit none
external sub
pointer (subptr,subpte)
external subpte
subptr = loc(sub)
call subpte()
[...]
subroutine sub
[...]
end subroutine sub

Указатель может быть изменен в ходе выполнения программы, и это изменит расположение, на которое указывает указанный. Однако при передаче указанных в качестве аргументов они обрабатываются как обычные переменные в вызываемой функции. Последующие изменения указателя не изменят базовый адрес массива, который был передан.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gfortran/Cray-pointers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API