计算化学公社

标题: 上古fortran代码中,用data给数组赋值的坑 [打印本页]

作者
Author:
beefly    时间: 2022-8-26 09:53
标题: 上古fortran代码中,用data给数组赋值的坑
本帖最后由 beefly 于 2022-8-26 11:10 编辑

考古fortran代码的时候,经常遇到用data语句给数组赋初值,但是用现今的fortran编译器可能会导致错误结果。

  1.       common /common1/ a1(3), a2(3)
  2.       call dat1
  3.       call dat2
  4.       write(*,*) 'in main:'
  5.       write(*,*) 'a1=',a1
  6.       write(*,*) 'a2=',a2
  7.       end

  8.       subroutine dat1
  9.       common /common1/ a1(3), a2(3)
  10.       data (a1(i),i=1,3)/ 1.0, 2.0, 3.0/
  11.       end

  12.       subroutine dat2
  13.       common /common1/ a1(3), a2(3)
  14.       data (a2(i),i=1,3)/-1.0,-2.0,-3.0/
  15.       end
复制代码

这段代码的本意,是在子程序dat1中给a1赋初值,在子程序dat2中给a2赋初值。ifort编译后运行,给出了预期的结果:
  1. in main:
  2. a1=   1.000000       2.000000       3.000000
  3. a2=  -1.000000      -2.000000      -3.000000
复制代码

而gfortran编译后,运行结果却是
  1. in main:
  2. a1=   1.00000000       2.00000000       3.00000000
  3. a2=   0.00000000       0.00000000       0.00000000
复制代码

在两个子程序中,由于不存在可执行语句,也可以把“subroutine”改成“block data”,然后删除主程序中的两个call语句。此时gfortran编译运行的结果又变成了
  1. in main:
  2. a1=   0.00000000       0.00000000       0.00000000
  3. a2=  -1.00000000      -2.00000000      -3.00000000
复制代码

这说明对于gfortran,位于同一个common block里的多个数组,只能在同一个subroutine或block data里用data一起赋初值。如果在不同的subroutine或block data里赋初值,需要改为直接赋值的可执行语句(subroutine),或者把common block拆开:
  1.       common /common1/ a1(3)
  2.       common /common2/ a2(3)
复制代码

  1.       dimension a1(3)
  2.       data a1/3*1.0/
  3.       data a1(2)/-2.0/
  4.       write(*,*) 'a1=',a1
  5.       end
复制代码

在给数组a1赋初值的时候,先全部设为1.0,再令第二个数组元素a(2)=-2.0。但是无论ifort还是gfortran,编译、运行的结果都是1.0!根据一些古籍提供的源代码,可能MS-V. Fortran编译器会给出想要的结果。这说明用data给某个数组赋初值的操作,能且只能做一次。





欢迎光临 计算化学公社 (http://bbs.keinsci.com/) Powered by Discuz! X3.3