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