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 specifier, Предыдущее: Поддержка констант Холлерита, Вверх: Расширения, реализованные в GNU Fortran [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.4.0/gfortran/Cray-pointers.html