プログラムでの配列のサイズの違いについて

このQ&Aのポイント
  • プログラムでの配列のサイズの違いについて質問があります。メインとサブで配列のサイズが異なっても問題ないやり方や、サブ側が動的に対応できるプログラムの書き方が知りたいです。
  • フォートランのプログラムで、メインとサブで配列のサイズが異なる場合に問題ないやり方や、サブ側が動的に対応できるプログラムの書き方について質問です。
  • フォートランのプログラムで、メインとサブで配列のサイズが異なる場合の対応方法について質問です。配列のサイズの違いによって、サブルーチンの使い回しができなくなるかどうかがわからないため、具体的なやり方を知りたいです。
回答を見る
  • ベストアンサー

プログラムでの配列の渡し方

ここではフォートランの問題としてお尋ねします。(フォートランのカテゴリがないのでプログラムの専門家に聞けそうなカテゴリに質問してます。) dimension a(100,100) ... call abc(a) ... stop end subroutine abc(b) dimenison b(100,1) ... return end というようなプログラムがあります。メインの方でa(100,100)と宣言してサブルーチンではb(100,1)で受けるというような処理です。 このようにメインとサブで配列のサイズが異るのはどのようなレベルで許容されるものでしょうか。考え方がわからないのでお尋ねします。私は厳密にサイズを合わせると思っていました。しかしそうだとサブルーチンの使い回しができなくなります。このような問題はC言語の配列の先頭のアドレス云々という問題と似ているのですが。2次元配列ということがわかっていて片方のサイズがわかると自ずからもう片方のサイズがわかるということなのでしょうか。 まとめますと、以下のような点がわからないということです。 1.メインとサブで配列サイズが異なっても問題ないやり方 2.サブ側が動的に対応できるようにするプログラムの書き方(同じサブルーチンだけど、呼び出すメイン側の配列サイズに自動で対応する方法) *などを使うのだろうと思いますが。 この部分はしっかり理解しないと大怪我するところなので確認したいと思っています。 (実験して試すというのではなく、仕様としてどうかということですが) よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • kngj1740
  • ベストアンサー率18% (197/1052)
回答No.1

INDEX順序と言うらしいです。メモリ上の割りつけは左側のINDEXが最初に変化するような割り付けになります。すなわちメモリ上の割り付けは a(1,1)、a(2.1)・・・a(100,1)、a(1,2)、a(2,2)・・・a(100,2)というように続きます。 a(100,100)をsub側て a(100,1)で受けても差し支え訳です。アセンブラに落とされたリストを見れば直ぐ分ります。

skmsk19410
質問者

お礼

回答ありがとうございました。 一般的な解説本には載っていないように思います。このあたりのことは慎重に考えないと失敗すると思います。特にCではそのようなことを説明する本をよく見ると思います。

関連するQ&A

  • FORTRAN subroutineと配列と繰り返し

     以下のように二次元配列の場合でsubroutineを使うときに、主プログラムで2重Doループ(iとj)で繰り返しをしているのですが、すでにsubroutineでDoループ(i)を用いて計算しています。これではsubroutineの利点をうまく使えていないと思うのですが、subroutineを使って配列、Doループをきれいにする方法をどなたか教えていただけませんか。  実際は4重ループ、4次元配列なので、プログラムをわかりやすくするためにサブルーチンを使いたいと思っています。 -------------------------------------------------------------- program S real,dimension(5,5) :: B real,dimension(5) :: A integer :: i,j do j=1,5 CALL sub1(A) do i=1,3 B(i,j)=A(i)*j write(*,*) B(i,j) end do end do end program S subroutine sub1(A) real,dimension(5) :: A integer :: i do i=1,3 A(i)=3.*i end do end subroutine sub1

  • fortran 配列受け渡し時の次元の一致

    fortran90、コンパイラはifortです。 普通メインプログラムとサブルーチン間での配列の受け渡しは、次元を揃えて渡すと思います。 とあるコード(以後コードA)を読んでいると、2次元配列を渡し、1次元配列で受け取っていました。 例 program test1 integer :: a(3,3) call testsub(a) end program subroutine testsub(b) integer :: b(9) end subroutine これが受け取り側でどう処理されているのかわからず、調べるために適当なテストコードを書きました。 a 123 456 789 ↓ b 123456789 になるとか 結果、コンパイルは通ったのですがサブルーチン側では全て0で置き換えられてしまいました。 コードAはpgiかなんかでコンパイルしていたようなのでコンパイラの違いでしょうか? よくわらなかったので質問させて頂きました。 質問をまとめますと、 (1)次元の異なる配列の受け渡しができるかどうか (2)その場合中身はどうなるか よろしくお願いします。 ---以下テストコード--- program testa implicit none integer :: a(3,3),i,j do i=1,3 do j=1,3 a(i,j)=j+(i-1)*3 enddo enddo do i=1,3 do j=1,3 write(6,*) a(i,j) enddo enddo call sub1(a) end program subroutine sub1(b) integer :: b(9),i do j=1,9 write(6,*) b(i),'sub' enddo end subroutine

  • フォートランの配列の受け渡し問題

    いまどき、フォートランの配列について質問します。 配列の実引数(メイン側の配列変数)とサブルーチン側の変数(仮引数の配列変数)の受け渡しですが、配列のサイズを変動させることが可能でしょうか。 program main dimension x(100) ! xの最大配列サイズ100 .... call abc(x,np) ! 実際にはxはnp(<100)個の配列とする。   .... subroutine abc(xx,nx) ! x->xx(仮引数,配列サイズはnx=np) dimension xx(1) ! 配列の先頭を示しておく。 .... こうしておくと、サブルーチンabcで利用する配列は呼び出し側でnp(=nx,=<100)を変更することによってサイズをダイナミックに変動できると思っています。実験すると大丈夫なようです。 では、2次元、3次元の配列では配列のサイズを変数でコントロールするにはどうしたらいいでしょうか。実引数と仮引数で名前以外の変数情報を一致させるというのが教科書的な対応だと思いますが、ダイナミックに変数を変化させるにはどうしたらいいでしょうか。 追加ですが、プログラムに対して外部データを入力させる場合のnamelist入力について解説しているサイトとか本があるでしょうか。これは古臭い(フォートランでさえ古いですが、さらに古い)やり方かと思いますが、解説本には載っていないようです。 以上、よろしくお願いします。 ところで、フォートランの復権なんてことはやはりないのでしょうか。ポインタなども導入されてC言語みたいになってきているとは思いますが。

  • フォートランのサブルーチンの内部変数

    すみません。科学技術系の人間でして、フォートランが現役なのです。 あるプログラムのことですが、サブルーチンの内部の変数についてサブルーチンを呼び出すごとに加算していくようなことを行っています。 do i=1,100 call abc(i)   ← サブルーチンabcを100回呼び出す enddo end subroutine abc(i) n=n+1        ←呼び出されるたびに和をとる。 write(*,*) n return end このようなシンプルなプログラムは問題ないのですが、少し複雑になるとどういうわけか、呼び出される度にnが初期化され、writeさせた結果常に1が表示されるという現象に会いました。 昔のコンパックフォートラン(MS-Fortran, DEC Fortranを継承)と、最近のIntel Fortran(最新版)で動作が異なります。前者では和を取ってくれますが、後者では初期化されて常に1が出力されます。(上記のプログラムは問題なしです。もう少し長いプログラムでの問題です。) 言語仕様の問題(すなわちフォートランのバージョン)なのか、コンパイラ仕様の問題なのか、C言語のように宣言の仕方で変ったりするようになったというようなことはないでしょうか。 以下に示すように和をとる変数をメインプログラム側に一旦見えるようにすると、インテル版でも思ったとおりの動作をします。 call abc(i,n) suboroutine abc(i,n) としてnをメイン側に露出する。 よろしくお願いします。

  • 動的配列の使い方の問題

    プログラムには動的配列というものがあり、配列なのですが、最初の宣言でサイズは指定しない(型は指定すると思いますが)というような動作ができるのだろうと思います(それ以外もあるかもですが)。 私が目指しているのはデータの総数がわからないけれど、データファイルを読み込んで総数をカウントしたらわかるのでそれを使ってメモリを確保するというようなことです。事例集を見ると以下のようなものはあります。 allocatable a(:) ..... データファイルを開いてカウントしたら100だった ..... allocate(a(100)) この使い方ってあんまりご利益がないように思います。カウントしたら100だったということですが、その時はデータをとりあえず読んでいるわけです。 配列サイズ100とわかって実際にアロケートしないと配列は利用できないものなのでしょうか。 これに関連して質問ですが、サブルーチンとか関数とか副プログラムに配列を渡して処理する場合、サブルーチン側の配列(仮引数)の型、サイズを指定しない方法があるでしょうか。メイン側で決めたものに従いますということなのですが。 例えばサブルーチン側の仮引数BについてB(*)などとしていたらメイン側の指定通りになっているということになるのでしょうか。動的な配列ということでお尋ねしているのですが、副プログラムの仮引数の配列がサイズ依存が消えたように見えるからこちらの方が動的に見えるのですが。サイズに関してはメインで宣言したらどうにでも対応します、という弾力性があります。もちろ使いまわしも容易になりますが。 言語ですが、お気づきとは思いますが、Fortranです(ハズイ感じ)。その他の言語の仕様でも参考になります。よろしくお願いします。

  • 副プログラムの変数について

    Fortranなのですが、以下のようなプログラムがあります。 call sub1 call sub1 end subroutine sub1 !save a write(*,*) a a=1.0 return end sub1というサブルーチンをメインから2回呼び出すだけです。そのサブルーチンの中の変数aですが、2回目に呼び出されたときに1回目に設定したa=1が保持されているようです。2回目の呼び出しで1回目に設定したa=1に対応した出力になっています。 Fortranはこのような動作をするのでしょうか。save aをコメントアウトしているのです。save aを指定したときだけそうなると思っていたのですが。cなどは細々とした設定ができるだろうと思います。このサンプルコードは実際にそうなっているという実験なのですが、どういう風に解釈したらいいでしょうか。〇〇保存属性とかです。昔からこうだったのでしょうか。使用したのはgfortran ver.9.3ですが。 

  • 配列サイズを明示せずサブルーチンに渡す方法

    プログラムのメインの方で2次元、3次元の高次元配列を設定してそれをサブルーチンに引き渡すことを考えています(しょっちゅうやっていることですが)。 この場合、サブルーチン側に汎用性を持たせるためにできるだけ配列のサイズを自動で渡すようにしたいと思っています(メインが変わるとそれに応じて自動対応)。そうしないとサブルーチンが汎用化せず、ケースバイケース(メイン側の配列のサイズが変わる場合それに応じてコードを書き変えなければならない)に応じなければならず、うっかりミスの間違いもおこりそうです。 配列のサイズを決めないサブルーチンの書き方を教えて頂きたいのですが。 なお、今回は配列はデータとして参照するだけで書き換えることはありません。 言語ですが、”サブルーチン”というだけあってFortranです。(Cのカテゴリだと答えを頂けるかなと思っているのですが。他に適当なところも無いようですが)

  • リファレンスをサブルーチンの戻り値にしてもOKですか?

    ■ サブルーチン内部で処理した結果を格納した、配列、ハッシュ、スカラーなどのデータを戻り値として利用する必要があります。その場合、どうするのが標準的なやり方でしょうか? ■ return (配列へのリファレンス, ハッシュへのリファレンス, スカラー); などとやってしまっても問題はないでしょうか? ■ 下のプログラムを試したところ、予想に反しちゃんと 「31415」と表示されました。 #!/usr/bin/perl -w sub subroutine{ my @a = (3, 1, 4, 1, 5); return \@a; } my $b = subroutine{}; print @$b; ■ サブルーチン内部で使用した変数へのリファレンスをサブルーチン 外で使っていいのだろうか? サブルーチンの処理が終了した時点でサブルーチン内部で使用した 変数はメモリーから消去されるのかと思ったものですから。

    • ベストアンサー
    • Perl
  • 配列をサブルーチンで処理するには

    初歩的な質問ですが、配列をサブルーチンに渡して処理を繰り返すためにはどのように配列を渡せばよいのでしょうか? わからないところはサブルーチンを呼び出すときの配列の渡し方と、サブルーチン部分での配列の受け取り方です。 下に簡単な図を書きましたのでお分かりの方お教えください。 -------------------------------------------------------- サブルーチンに処理を渡す部分(この部分がわかりません) sub abc{ 配列の受け取り(この部分がわかりません) foreach( 配列 ){ 処理 } } -------------------------------------------------------- よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • モジュールとなったライブラリ集の利用法

    以下、長文ですみません。 サブルーチンとか関数に関するプログラム集というものがあり、自分でメインを適当に作ってそれらを呼び出して使うというライブラリ集のようなものがあります。昔からあるもので各言語に応じた本なども多数出版されています。 Fortranなのですが、F77の頃は以下のパターンが1つのファイルで延々と1万行ぐらい続くものです。ファイル名:A.f ---------------- 以下の形式のサブルーチン群の羅列 subroutine abc() いろいろ return end ---------------- このようなものは、例えば、 gfortran -c A.f としてリンクなしでコンパイルし、オブジェクトA.oが出力され、 メインプログラム(B.f)から呼び出す場合、 gfortran B.f -o A.o とすると、実行形式が出力されます(ここまで前置きが長くてすみません)。 さて、Fortran95だと状況が一変します。 A.f95だと以下のように変更されています(A.fの後継としてのA.f95)。 ------------- module A interface.... public... private... そしてサブルーチン群 subroutine abc() いろいろ return end subroutine abc end module A ------------ これを gfortran -c A.f95 とリンクなしでコンパイルすると、A.mod, A.oという2つのファイルが出力されます。 その後、メイン(B.f95)の作成ですが、モジュールA.modを読み込むため、 USE A を先頭にし,中身をF95のフォーマットにしています。その後、 gfortran B.f95 -o A.o あるいは gfortran B.f95 とするのですが、B.f95からcallしているA.f95の中のサブルーチンが発見できないというエラーになります。これら(A.f95, B.f95, A.o, A.mod)はすべて同一フォルダ内部のファイルです。 ここで万事休すなのですが、何かFortran95の処理で間違っているところがあるでしょうか。私がFortran95の処方を間違っているからではないかと思いますが、対処方法についてもしご存じでしたら、よろしくお願いします。 ※カテゴリ違いかもですが、ここしか聞く当てがないと思っています。

専門家に質問してみよう