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