在 Fortran 中使用全局变量时的错误结果
Wrong result when using a global variable in Fortran
我正在学习 Fortran 的基础知识。我创建了一个初始化矩阵的简单子程序:
program test
integer, parameter :: n = 1024
real :: a(n, n)
call init(a)
write (*, *) a(1, 1)
end program
subroutine init(a)
real :: a(n, n)
a(:, :) = 3.0
end subroutine
那么输出是 0.0
而不是预期的 3.0
。除此之外,valgrind
表示:
==7006== Conditional jump or move depends on uninitialised value(s)
==7006== at 0x400754: init_ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x4007A4: MAIN__ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x40083B: main (in /home/marcin/proj/mimuw/fortran/test)
为什么? n
参数已被编译器正确识别,应该是全局参数。
我用gfortran 6.3.1编译程序
n
不是全局变量,是主程序的局部变量
子程序是完全独立于主程序的编译单元,不共享任何信息
子例程可以 "see" 父模块的其他变量,如果它是模块过程,或者父(宿主)过程或程序的变量,如果它是内部过程。
一定要阅读Fortran程序的结构,尽可能多地使用模块。优先使用模块而不是内部程序。您将在 link.
中看到如何将子例程放入模块或如何使其成为主程序的内部
我没有提到公共块,只是不要使用它们,它们已经过时了。并记住在每个编译单元中使用 implicit none
。
假设到处都需要,那f77时代用COMMON块,现在用MODULE。
我大写了大部分的变化。如果没有错误,给出了一些考虑理解子程序中 N 的方法,并且在这里也可能值得尝试一个元素函数。
MODULE MyMODULE
integer, parameter :: n = 1024
END MODULE MyMODULE
!%%%%%%%%%%
program test
USE MyModule
IMPLICIT NONE
! done up in ˆmoduleˆ...! integer, parameter :: n = 1024
REAL, DIMENSION(n,n) :: A
CALL Alternative_Init(A, 3.3)
WRITE (*,*) a(1, 1)
CALL Alternative2_Init(A, n, 1.23)
WRITE (*,*) a(1, 1)
call init(a)
write (*, *) a(1, 1)
END PROGRAM TEST
!%%%%%%%%%%
subroutine init(a)
USE MyModule
IMPLICIT NONE
real :: a(n, n)
a(:, :) = 3.0
RETURN
END SUBROUTINE init
!%%%%%%%%%%
SUBROUTINE Alternative_Init(a, Val4A)
USE MyModule
IMPLICIT NONE
REAL, DIMENSION(:,:) , INTENT(INOUT) :: a
REAL , INTENT(IN ) :: Val4A
a(:, :) = Val4A
! or just... A = Val4A ! which does them all too.
RETURN
END SUBROUTINE Alternative_Init
!%%%%%%%%%%
SUBROUTINE Alternative2_Init(a, n, Val4A)
!!!! USE MyModule
IMPLICIT NONE
INTEGER , INTENT(IN ) :: n
REAL, DIMENSION(n,n) , INTENT( OUT) :: a
REAL , INTENT(IN ) :: Val4A
A = Val4A
RETURN
END SUBROUTINE Alternative2_Init
我正在学习 Fortran 的基础知识。我创建了一个初始化矩阵的简单子程序:
program test
integer, parameter :: n = 1024
real :: a(n, n)
call init(a)
write (*, *) a(1, 1)
end program
subroutine init(a)
real :: a(n, n)
a(:, :) = 3.0
end subroutine
那么输出是 0.0
而不是预期的 3.0
。除此之外,valgrind
表示:
==7006== Conditional jump or move depends on uninitialised value(s)
==7006== at 0x400754: init_ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x4007A4: MAIN__ (in /home/marcin/proj/mimuw/fortran/test)
==7006== by 0x40083B: main (in /home/marcin/proj/mimuw/fortran/test)
为什么? n
参数已被编译器正确识别,应该是全局参数。
我用gfortran 6.3.1编译程序
n
不是全局变量,是主程序的局部变量
子程序是完全独立于主程序的编译单元,不共享任何信息
子例程可以 "see" 父模块的其他变量,如果它是模块过程,或者父(宿主)过程或程序的变量,如果它是内部过程。
一定要阅读Fortran程序的结构,尽可能多地使用模块。优先使用模块而不是内部程序。您将在 link.
中看到如何将子例程放入模块或如何使其成为主程序的内部我没有提到公共块,只是不要使用它们,它们已经过时了。并记住在每个编译单元中使用 implicit none
。
假设到处都需要,那f77时代用COMMON块,现在用MODULE。
我大写了大部分的变化。如果没有错误,给出了一些考虑理解子程序中 N 的方法,并且在这里也可能值得尝试一个元素函数。
MODULE MyMODULE
integer, parameter :: n = 1024
END MODULE MyMODULE
!%%%%%%%%%%
program test
USE MyModule
IMPLICIT NONE
! done up in ˆmoduleˆ...! integer, parameter :: n = 1024
REAL, DIMENSION(n,n) :: A
CALL Alternative_Init(A, 3.3)
WRITE (*,*) a(1, 1)
CALL Alternative2_Init(A, n, 1.23)
WRITE (*,*) a(1, 1)
call init(a)
write (*, *) a(1, 1)
END PROGRAM TEST
!%%%%%%%%%%
subroutine init(a)
USE MyModule
IMPLICIT NONE
real :: a(n, n)
a(:, :) = 3.0
RETURN
END SUBROUTINE init
!%%%%%%%%%%
SUBROUTINE Alternative_Init(a, Val4A)
USE MyModule
IMPLICIT NONE
REAL, DIMENSION(:,:) , INTENT(INOUT) :: a
REAL , INTENT(IN ) :: Val4A
a(:, :) = Val4A
! or just... A = Val4A ! which does them all too.
RETURN
END SUBROUTINE Alternative_Init
!%%%%%%%%%%
SUBROUTINE Alternative2_Init(a, n, Val4A)
!!!! USE MyModule
IMPLICIT NONE
INTEGER , INTENT(IN ) :: n
REAL, DIMENSION(n,n) , INTENT( OUT) :: a
REAL , INTENT(IN ) :: Val4A
A = Val4A
RETURN
END SUBROUTINE Alternative2_Init