Spec-Zone.ru › GNU Fortran 5

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-5.4.0/gfortran/Cray-pointers.html

Spec-Zone.ru

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