Указатель на производный тип, который содержит размещаемый массив
Вообще говоря, я хочу переименовать размещаемые переменные в производном типе, которые передаются через аргументы подпрограммы. Написание всего с "производным%type_xx" не так приятно. Кроме того, я не хочу тратить дополнительную память на копирование значений производного типа в новую переменную, которая стоит новой выделенной памяти. Кроме того, я знаю, что по многим причинам распределенные массивы предпочтительнее, чем указатели. Я пытаюсь определить указатели на размещаемую переменную, но не удалось. Я попробовал это, потому что я хочу упростить мой код, чтобы он был читабельным и не был слишком длинным. Интересно, есть ли способ достижения цели? Благодарю.
Вот демонстрационный код:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1) :: input
input%longname_1 = input%longname_1 + input%longname_2 ! Use one line to show what I mean
END SUBROUTINE
И вот что не удалось:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1),TARGET :: input
REAL,POINTER :: a => input%longname_1 &
& b => input%longname_2
a = a + b ! much better for reading
END SUBROUTINE
Это кажется небольшой проблемой, но я хотел бы прочитать мой код без особых проблем в будущем. Так какой же самый лучший вариант? Большое спасибо.
2 ответа
Вы можете использовать конструкцию ASSOCIATE, чтобы связать простое имя с более сложным указателем или выражением.
Вы также можете использовать подобъекты производного типа в качестве фактических аргументов для процедуры, которая выполняла операцию.
Ваш подход с указателем не удался, потому что у вас было несовпадение рангов - вы пытались связать скалярные указатели с целевыми объектами массива. У вас также могут быть проблемы, если явный интерфейс к вашей процедуре не был доступен в вызывающей области. Явный интерфейс необходим для процедур с фиктивными аргументами с атрибутом TARGET.
Использование указателей для такого простого именования имен может снизить способность компилятора оптимизировать код. Что-то вроде ASSOCIATE должно быть предпочтительным.
Обновление: после того, как @IanH сделал свой комментарий, я вернулся, чтобы проверить: я был совершенно и совершенно не прав, почему ваш код провалился. Как он указал в своем ответе, основная проблема заключается в том, что указатель и цель должны иметь одинаковый ранг, поэтому вам придется объявить a
а также b
как:
real, pointer :: a(:), b(:)
Во-вторых, прежде чем вы сможете на самом деле указывать эти указатели на цели, цели должны быть распределены. Вот пример, который работает:
program allocatable_target
implicit none
type :: my_type
integer, allocatable :: my_array(:)
end type my_type
type(my_type), target :: dummy
integer, pointer :: a(:)
allocate(dummy%my_array(10))
a => dummy%my_array
a = 10
print *, dummy%my_array
end program allocatable_target
Если у вас есть совместимый с Fortran 2003 компилятор, вы можете использовать associate
- который специально предназначен для такого рода вопросов. Вот пример:
program associate_example
implicit none
type :: my_type
integer, allocatable :: long_name_1(:), long_name_2(:)
end type my_type
type(my_type) :: input
integer :: i
allocate(input%long_name_1(100), input%long_name_2(100))
associate (a=>input%long_name_1, b=>input%long_name_2)
a = (/ (i, i = 1, 100, 1) /)
b = (/ (2*i+4, i = 1, 100, 1) /)
a = a + b
end associate
print *, input%long_name_1
end program associate_example
Внутри associate
блок, вы можете использовать a
а также b
как сокращение для объявленных переменных с более длинными именами.
Но кроме этого, я предлагаю вам получить редактор с правильным завершением кода, тогда длинные имена переменных больше не являются проблемой. Сейчас я пробую Atom и очень доволен этим. Но я использовал vim
с правильными расширениями в течение длительного времени.