2016-08-11 11 views
2

一般的に言えば、派生型の変数の名前を、サブルーチンの引数に渡す名前に変更したいとします。 'derived%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 

それは小さな問題のように思えるが、私はあまり痛みなし私のコードを読みたいです未来。最適な選択肢は何ですか?どうもありがとう。

答えて

5

ASSOCIATE構文を使用して、単純な名前をより複雑な指定子または式に関連付けることができます。

操作を実行したプロシージャの実際の引数として派生型のサブオブジェクトを使用することもできます。

スカラーポインタを配列ターゲットに関連付ける際に、ランクが一致していないためにポインタの接近が失敗しました。また、プロシージャーへの明示的なインタフェースが呼び出しスコープで使用できなかった場合にも問題が発生している可能性があります。仮引数がTARGET属性を持つプロシージャーの場合は、明示的なインターフェースが必要です。

この種のシンプルな名前エイリアシングのためにポインタを使用すると、コンパイラがコードを最適化する能力が低下する可能性があります。 ASSOCIATEのようなものが好まれるはずです。

+0

ありがとうございました! – Ruizhi

4

更新: @IanHがコメントした後、私はチェックに戻りました:あなたのコードが失敗した理由は完全に完全に間違っていました。あなたが実際にこれらを指すことができます前に、

real, pointer :: a(:), b(:) 

第二:彼は彼の答えで指摘したように、主な問題は、あなたにabを宣言する必要があると思いますので、ポインタとターゲットは、同じランクを持っている必要があるということですターゲットへのポインタ、ターゲットを割り当てる必要があります。 - 特にこの種の問題のために意味され

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ブロックの中で、あなたが宣言した長い名前の変数のためのショートフォームとしてabを使用することができます。

しかし、これ以外にも、適切なコード補完でエディタを作成することをお勧めします。長い変数名はそれ以上の問題ではありません。現時点では、私はAtomを試しており、それにはとても満足しています。しかし私はvimを長い間適切に拡張して使用してきました。

+0

ありがとう@IanH。私はそれが今正しいことを願っています。 – chw21

+0

関連するコンストラクトの詳細な使い方を示してくれてありがとう! – Ruizhi

+0

警告:セレクタに 'allocatable'または' pointer'属性がある場合、associate_nameは属性を継承しません。ただし、セレクタが配列の場合、associate_nameは各次元の同じランクと上限と下限を想定し、セレクタがダミー変数で、 'intent'、' target'、またはvolatile属性を持つ場合、associate_nameは同じ属性。 – jlokimlin

関連する問題