- ベストアンサー
FORTRANのCOMMON文
COMMON文について教えてください。 本を見ると R(2,2)という配列を共有したいとき R(2,2)を主プログラムで定義しているとき 主プログラムとR(2,2)を使うサブルーチンの 両方でCOMMON文を書く必要がある。 というような内容でした。 そこで配列を宣言して両方にCOMMON文を書くとエラーが出ます。そこで配列宣言を消去するとエラーがなくなります。COMMON文を使うときは配列(変数)を宣言する必要はないのですか?(暗黙の型宣言は使わない場合を考えています。) またCOMMON文では変数の型宣言をするとエラーが出るし暗黙の型宣言に従って使うと変数には意味を付けて使っているので都合が悪いときもあります。 倍精度で変数を使いたい時とかにも困りますし。 COMMON文で自由な型で変数を使うにはどうしたらいいのでしょうか? 教えてください。お願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> double precision W1 R1の間違いじゃないですか? これだとメインとサブでR1がdoubleとrealになるのでコモンブロックのサイズが合わないと警告が出てくると思いますけど。 迷ったときには規格を、ということでFORTRAN 77 Full Language(ANSI X3J3/90.4)を見てみました。 下記は原文にインデックスをつけて見やすくしたものです。 http://www.fortran.com/fortran/F77_std/rjcnf-8.html#sh-8.3.1 原文はこちら。 http://www.fortran.com/fortran/F77_std/f77_std.html commonにはvariable names、array names、array declaratorsが使えると書いているようなので、 integer r(5) common /a/ r は特に問題なく使えるような気がします。 全部を読んだわけではないので、どこかに但し書きがあるかもしれませんが。 一応compaqのサイト(多分fortranの日本語ドキュメントはここが一番充実している) http://www1.jpn.hp.com/products/software/development/dvf/docs/vf-html/az/az03_26.htm も見てみましたが、ここでも、 integer r(5) common /a/ r のような感じでかかれていましたね。 ここのドキュメント(Compaq Visual Fortran用)がそのまますべてのコンパイラに当てはめられるわけでもないですけど。 #3さんの(スペル忘却)の部分はEQUIVALENCEのことですかね? http://www1.jpn.hp.com/products/software/development/dvf/docs/vf-html/Lr/lr05_07.htm 参考になりそうなURLを載せておきます。 マニュアル類 http://www.fortran.com/fortran/F77_std/rjcnf.html http://www1.jpn.hp.com/products/software/development/dvf/docs/index.html http://www.imit.chiba-u.ac.jp/services/ed_rsch/sr8000/manual/6a303313/html/m0240001.htm ソースコード(サンプル) http://www.ccl.net/cca/software/SOURCES/FORTRAN/allen-tildesley-book/index.shtml http://ion.le.ac.uk/cutlass/merge/merge.f.html http://www.physics.carleton.ca/courses/75.502/slides/projects/1996/joanne/node1.html http://spallation.physics.sc.edu/~blanpied/research/chase/source.htm
その他の回答 (4)
#3さんの(スペル忘却)の部分はEQUIVALENCEのことですかね? ご指摘の通りです。感謝します。
お礼
おかげさまで望みのプログラムができました。 どうもありがとうございました。
引数の障害(引数で使っている変数と同名の引数を別に宣言した等)の問題が存在しないとします。 無名共通領域は common r と宣言された場合 common /a/ r は有名共通領域で共通領域の名称は「a」となります。 しばらく.使ってないので.スペルが間違っている可能性が大きいです。 また.どうゆうわけか連続半角空白が1文字の半角空白に化けるので.桁あわせをしてください。 mainprogram main paramater ICADATN=100 dimision COMDATA(ICDATAN) common comdata (適当な宣言文) integet r dimision r(2,2) (スペル忘却) comdata(40),r 先に書いたエクスターナル文は参照変数の領域を確保する宣言なので.間違い。 (適当な実行文) R(2,2)=1 call exit (スペル疑問) end subroutine sub01 dimision COMDATA(ICDATAN) common comdata integet r dimision r(2,2) (スペル忘却) comdata(40),r write (1,600) r(2,2) 600 format (1h i7) (書式忘却) exit (スペル疑問) end sub これで.無名共通領域の40番目の配列以後にRという配列を割り当てることが出来ました。 変数Rは.配列ですから.配列の一部だけを共通領域として定義できません。 注意点としては. 配列を宣言する前に.変数の型を宣言すること. 配列を宣言してから.COMMON文をいれること。 配列数が異なるとエラーになります(文法か実行時かりんかーで)。私の場合には.定数宣言を使いました。 この方法は.巨大な配列をひとつ用意する必要がありますが.任意の大きさの配列を実質的に動的に割り当てられるので.データ数が異なる場合には結構便利です。
お礼
ありがとうございました。 edogawaranpoさんの回答を参考にして もう少し考えてみます
たしか.この方法は. 無名共通領域に限る という条件がついたかと思います。 それから.言語系によっては.宣言の順番が決められていて. commonを先に宣言する場合と.後に宣言する場合. 仮想変数で宣言しておいて.ext(すべる忘却)で接続する場合. 配列多きさをpara(スペル忘却)で指定する必要がある場合 等の制限があります。
補足
???うーん・・・・・おっしゃられることがよくわかりません。 FORTRANは初心者なのでもう少しやさしく説明してもらえませんか?
- hofuhofu
- ベストアンサー率70% (336/476)
再登場です(^^;) 軽く調べて見ましたけど、ちゃんと明記されているようなサイトは見つけられませんでしたね。 で、ちょっと試してみました。 一応、 integer r(5) common /a/ r r(3)=5.5 call hoge() stop end subroutine hoge() integer r common /a/ r(5) write(*,*) r(3) return end とすると、コンパイル(g77使用)も無事通り、結果もちゃんと5.5が桁落ちして5が表示されるようになりました。 (メインとサブで配列を宣言している位置が違っています) r()の中を別々の値ににするとちゃんとコモンブロックaのサイズが合わないと警告が出てくるので、integerとcommon間で配列として認識しているようです。 要は配列にするのはどちらか一方でいいということですね。 他方はそれに合わせて自動的に配列になっているみたいです。 両方とも配列にすると、無効な宣言だと言われてしまいました。
補足
試しに私もプログラムを書いてみました。 double precision R1(0:1,0:1) common /a/ R1 data R1/1.0023e-2,2.35234e-4,11.2364e-5,2.234789e-8/ call test() end subroutine test() double precision W1 common /a/ R1(0:1,0:1) do 10 i=0,1 do 20 j=0,1 print *,R1(i,j) 20 continue 10 continue end これの実行結果は 2.000000 -1.0842022E-19 1.035368 0.6829398 となりました。 このプログラムのどこが原因で このような結果になったのでしょうか?
お礼
おかげさまで望みのプログラムが完成しました。 また機会があれば教えてください。 ありがとうございました。