6.1.14 Указатели 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
Указатель может быть изменен в ходе выполнения программы, и это изменит местоположение, на которое указывает указываемая переменная. Однако, когда указываемые переменные передаются в качестве аргументов, они обрабатываются как обычные переменные в вызываемой функции. Последующие изменения указателя не изменят базовый адрес массива, который был передан.
Далее: Спецификатор CONVERT, Предыдущее: Поддержка констант Холлерита, Вверх: Расширения, реализованные в GNU Fortran [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-6.4.0/gfortran/Cray-pointers.html