Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

риложение3. Организация данных

1.Адресная переменная не может быть формальным параметром, именем функции или элементом общего блока. Адресную переменную нельзя инициализировать при ее объявлении или в операторе DATA. Указатель не может появляться в операторе объявления типа и не может быть инициализирован в операторе DATA.

2.Операторы ALLOCATE и DEALLOCATE не могут быть использованы с целочисленными указателями.

Указатель может быть размещен на начало свежей области памяти, выделяемой функцией MALLOC. После использования выделенная память может быть освобождена встроенной подпрограммой FREE.

Пример. Сформировать область памяти, занося в байт по адресу p0 + k натуральное число k (k = 0, 127, 1).

byte gk

 

integer k, size /127/, p0

 

pointer(p, gk)

! Функция MALLOC возвращает начальный адрес

p0 = malloc(size)

! выделенной памяти

p = p0

! Установим указатель p в начало выделенной

do k = 0, size

! памяти

gk = int(k, kind = 1)

! В ячейку с адресом p заносится значение gk

p = p + 1

! Переход к следующему байту памяти

end do

! Просмотр памяти

print '(10i3)', (gk, p = p0, p0 + 5)

! 1 2 3 4 5 6

call free(p0)

! Подпрограмма FREE освобождает выделенную

end

! функцией MALLOC память

Целочисленные указатели являются расширением CVF и FPS над стандартами Фортран 90 и 95, и поэтому с ними можно работать при отсутствии директивы $STRICT или опции компилятора /4Ys. В основном целочисленные указатели предназначены для организации доступа к произвольной, доступной из программы области памяти ЭВМ.

Замечание. Целочисленные указатели Фортрана подобны указателям СИ. Порядок передачи целочисленных указателей в СИ-функции и приема указателей СИ в Фортран-процедуре рассмотрен в [1].

3.11. Ссылки и адресаты

Память под переменную может быть выделена на этапе компиляции или в процессе выполнения программы. Переменные, получающие память на этапе компиляции, называются статическими. Переменные, получающие память на этапе выполнения программы, называются

динамическими.

Ссылки - это динамические переменные. Выделение памяти под ссылку выполняется либо при ее размещении оператором ALLOCATE, либо после

95

О. В. Бартеньев. Современный ФОРТРАН

ее прикрепления к размещенному адресату. В последнем случае ссылка занимает ту же память, которую занимает и адресат.

3.11.1. Объявление ссылок и адресатов

Для объявления ссылки (переменной с атрибутом POINTER) используется атрибут или оператор POINTER, который, конечно, не следует смешивать с оператором объявления целочисленного указателя. Адресатом может быть:

прикрепленная ссылка;

переменная, имеющая атрибут TARGET (объявленная с атрибутом TARGET или в операторе с тем же именем);

выделенная оператором ALLOCATE свежая область памяти.

Ссылками и адресатами могут быть как скаляры, так и массивы любого встроенного или производного типа.

Пример:

! Объявление с использованием атрибутов

integer(4), pointer :: a, b(:), c(:,:)

! Объявление ссылок

integer(4), target, allocatable :: b2(:)

! Объявление адресата

integer(4), target :: a2

! Объявление с использованием операторов POINTER и TARGET

integer(4) d, e, d2 /99/

 

pointer d, e

! Объявление ссылок

target d2

! Объявление адресата

3.11.2. Прикрепление ссылки к адресатам

Для прикрепления ссылки к адресату используется оператор =>. После прикрепления ссылки к адресату можно обращаться к адресату, используя имя ссылки. То есть ссылка может быть использована в качестве второго имени (псевдонима) адресата.

Пример:

integer, pointer :: a, d, e

 

! Объявление ссылок

 

 

integer, pointer, dimension(:) :: b

 

 

 

 

 

 

 

integer, target, allocatable :: b2(:)

! Объявление адресатов

 

 

integer, target :: a2, d2 = 99

 

 

 

 

 

 

 

allocate(b2(5))

 

! Выделяем память под массив-адресат

a2 = 7

 

 

 

 

 

 

 

a => a2

 

! Прикрепление ссылки к адресату

b2 = (/1, -1, 1, -1, 1/)

 

! Изменение ссылки приводит к

 

b => b2

 

! изменению адресата, а изменение адресата

b = (/2, -2, 2, -2, 2/)

 

! приводит к изменению ссылки

 

print *, b2

 

!

2

-2

2

-2

2

b2 = (/3, -3, 3, -3, 3/)

 

 

 

 

 

 

 

print *, b

!

3

-3

3

-3

3

 

96

 

 

 

 

риложение3. Организация данных

a => d2

! Теперь ссылка a присоединена к d2

d => d2; e => d2

! Несколько ссылок присоединены к одному адресату

print *, a, d, e

!

99

99

99

a = 100

! Изменение a вызовет изменение всех

 

! ассоциированных с a объектов

print *, a, d, e, d2

!

100

100

100 100

deallocate(b2)

! Освобождаем память

nullify(b)

! Обнуление ссылки

end

 

 

 

 

Нельзя прикреплять ссылку к не получившему память адресату, например:

integer(4), pointer :: b(:)

integer(4), allocatable, target :: b2(:)

b => b2

! Ошибочное прикрепление ссылки

allocate(b2(5))

! к неразмещенному адресату

b2 = (/1, -1, 1, -1, 1/)

 

print *, b

 

Если объект имеет атрибуты TARGET или POINTER, то в ряде случаев такие же атрибуты имеет его подобъект. Так, если атрибут TARGET (POINTER) имеет весь массив, то и сечение массива, занимающее непрерывную область в памяти, и элемент массива обладают атрибутом

TARGET (POINTER), например:

integer, target :: a(10) = 3

 

integer, pointer :: b(:), bi

 

b => a(1:5)

! Ссылка и адресат полностью тождественны

!Ошибочен оператор прикрепления ссылки к нерегулярному сечению

!массива, имеющему атрибут target: b => a(1:5:2)

bi => b(5)

! Элемент массива также имеет атрибут POINTER

print *, b

!

3

3

3

3

3

Однако подстрока строки, имеющей атрибуты TARGET или POINTER, этими атрибутами не обладает, например:

character(len = 10), target :: st = '1234567890'

character(len = 5), pointer :: ps2

 

ps2 => st(:5)

! Ошибка

Если адресатом является ссылка, то происходит прямое копирование ссылки. Поэтому адресатом в операторе прикрепления ссылки может быть произвольное заданное индексным триплетом (разд. 4.5) сечение массивассылки. Само же заданное векторным индексом сечение не может быть адресатом ссылки. Например:

character(len = 80), pointer :: page(:), part(:), line, st*10

allocate(page(25))

 

part => page

! Было бы ошибкой, если бы page

part => page(5:15:3)

97

О. В. Бартеньев. Современный ФОРТРАН

 

! имел атрибут TARGET

line => page(10)

! Элемент массива также имеет атрибут POINTER

st => page(2)(20:29)

! Ошибка: подстрока не обладает атрибутом POINTER

Если ссылка-адресат не определена или откреплена, то копируется состояние ссылки. Во всех остальных случаях адресаты и ссылки становятся тождественными (занимают одну и ту же область памяти).

Тип, параметры типа и ранг ссылки в операторе прикрепления ссылки должны быть такими же, как и у адресата. Если ссылка является массивом, то она воспринимает форму адресата. При этом нижняя граница всегда равна единице, а верхняя - размеру экстента массива-адресата. Например:

integer, pointer :: a(:)

integer, target :: i, b(10) = (/ (i, i = 1, 10) /)

! Нижняя граница массива a равна единице, верхняя - трем

a => b(3:10:3)

 

 

 

 

print *, (a(i), i = 1, size(a))

!

3

6

9

Такое свойство ссылок позволяет заменить ссылкой часто применяемое сечение и обращаться к его элементам, используя в каждом его измерении индексы от 1 до n, где n - число элементов сечения в измерении.

Ссылка может быть в процессе выполнения программы прикреплена поочередно к разным адресатам. Несколько ссылок могут иметь одного адресата. Факт присоединения ссылки к адресату можно обнаружить, применив справочную функцию ASSOCIATED, имеющую синтаксис:

result = ASSOCIATED(ссылка [, адресат])

Параметр адресат является необязательным. Если параметр адресат отсутствует, то функция возвращает .TRUE., если ссылка присоединена к какому-либо адресату. Если адресат задан и имеет атрибут TARGET, то функция возвращает .TRUE., если ссылка присоединена к адресату. Функция также вернет .TRUE., если и ссылка и адресат имеют атрибут POINTER и присоединены к одному адресату. Во всех других случаях функция возвращает .FALSE.. Возвращаемое функцией значение имеет стандартный логический тип.

Пример:

real, pointer :: c(:), d(:), g(:)

 

real, target :: e(5)

 

logical sta

! Прикрепляем ссылки c и d к адресату

c => e

d => e

! В первых трех случаях sta равен .TRUE.

sta = associated(c)

sta = associated(c, e)

! в последнем - .FALSE.

sta = associated(c, d)

 

sta = associated(g)

 

98