Pointers 指向包含可分配数组的派生类型的指针

Pointers 指向包含可分配数组的派生类型的指针,pointers,fortran,derived-types,allocatable-array,Pointers,Fortran,Derived Types,Allocatable Array,一般来说,我想重命名通过子例程参数传递的派生类型中的可分配变量。使用“派生的%type_xx”编写所有内容都不是那么令人愉快。此外,我不想在将派生类型的值复制到新变量上花费额外的内存,这会占用新分配的内存。此外,我知道由于许多原因,可分配数组比指针更受欢迎。我试图定义指向可分配变量的指针,但失败了。我尝试这样做是因为我想简化我的代码,既要可读又不要太长。我想知道是否有办法实现这个目标?谢谢 下面是演示代码: Module module_type IMPLICIT NONE TYPE ty

一般来说,我想重命名通过子例程参数传递的派生类型中的可分配变量。使用“派生的%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

这似乎是一个小问题,但我希望在将来阅读我的代码时不要太痛苦。那么最好的选择是什么?非常感谢。

您可以使用关联构造将简单名称与更复杂的指示符或表达式关联起来

还可以将派生类型的子对象用作执行该操作的过程的实际参数

指针方法失败,因为秩不匹配-您试图将标量指针与数组目标关联。如果过程的显式接口在调用范围中不可用,您可能也会遇到问题。对于具有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
作为声明的较长命名变量的缩写


但除此之外,我建议您获得一个具有适当代码完成的编辑器,那么长变量名就不再是什么问题了。目前我正在尝试,对此我很满意。但是我已经使用了
vim
和适当的扩展很长时间了。

非常感谢您!感谢您展示相关构造的详细使用!警告:如果选择器具有
可分配
指针
属性,则关联名称不会继承该属性。但是,如果选择器是一个数组,则associate_name将采用每个维度的相同秩和上下界,如果选择器是一个伪变量,并且具有
intent
target
volatile
属性,则associate_name将采用相同的属性。