Fortran90模块与接口正确结构及GCC-11 USE语句报错求解
问题根源
你遇到的报错是Fortran语法强制的声明顺序规则和INCLUDE语句的文本替换机制共同导致的:
- Fortran标准明确规定:所有
USE语句必须放在所在程序单元(这里是AFprep子程序)的所有其他声明语句之前,包括INTERFACE块、INCLUDE插入的内容、变量/参数声明等。 INCLUDE 'mpif.h'属于文本级替换,编译器会直接把mpif.h的全部内容插入到你写INCLUDE语句的位置,而旧版mpif.h内部已经定义了大量MPI相关的INTERFACE块。
你的原始代码展开后实际顺序为:
IMPLICIT NONE [mpif.h内容,包含大量INTERFACE块] USE some_module [你自定义的INTERFACE块]
这就导致USE some_module确实出现在了INTERFACE块之后,完全符合编译器的报错逻辑。你之前调整USE和自定义INTERFACE的顺序没有作用,是因为mpif.h内部的INTERFACE还是在USE之前。
Fortran90+声明区正确顺序
标准要求的子程序/函数/主程序声明区顺序如下:
- 第一部分:所有
USE模块加载语句 - 第二部分:
IMPLICIT语句(通常是IMPLICIT NONE) - 第三部分:
INCLUDE语句、自定义INTERFACE块、参数声明、变量声明、类型声明等其他内容
解决方法
方法1(推荐):使用现代MPI模块替代mpif.h
目前主流MPI实现都支持USE mpi的写法,相比include旧头文件有类型检查更严格、语法更规范的优势,修改后代码如下:
SUBROUTINE AFprep (ida, idb, jda, jdb, kda, kdb ) ! 所有USE放在最前 USE some_module USE mpi IMPLICIT NONE interface SUBROUTINE nothing (azf, ata) REAL, INTENT(IN) :: azf ( : , : , : ) REAL, INTENT(IN) :: ata ( : , : , : ) END SUBROUTINE nothing end interface REAL, PARAMETER :: PI = 3.14159265 REAL( 8 ), PARAMETER :: DPI = 3.14159265358979324D0 REAL, PARAMETER :: PI180 = PI / 180.0 REAL, PARAMETER :: GRAV = 9.80622 INTEGER, INTENT(IN) :: ida, idb, jda, jdb, kda, kdb REAL :: aensf REAL, ALLOCATABLE, SAVE :: densq ( : , : , : ) integer :: i, j, status(MPI_STATUS_SIZE) character (len = 50) :: myfmt END SUBROUTINE AFprep
方法2:保留mpif.h,调整语句顺序
如果受环境限制必须使用旧头文件,只需要把USE语句移到INCLUDE之前即可:
SUBROUTINE AFprep (ida, idb, jda, jdb, kda, kdb ) ! 所有USE放在最前 USE some_module IMPLICIT NONE ! INCLUDE放在USE和IMPLICIT NONE之后 include 'mpif.h' interface SUBROUTINE nothing (azf, ata) REAL, INTENT(IN) :: azf ( : , : , : ) REAL, INTENT(IN) :: ata ( : , : , : ) END SUBROUTINE nothing end interface ! 后续声明保持不变 REAL, PARAMETER :: PI = 3.14159265 REAL( 8 ), PARAMETER :: DPI = 3.14159265358979324D0 REAL, PARAMETER :: PI180 = PI / 180.0 REAL, PARAMETER :: GRAV = 9.80622 INTEGER, INTENT(IN) :: ida, idb, jda, jdb, kda, kdb REAL :: aensf REAL, ALLOCATABLE, SAVE :: densq ( : , : , : ) integer :: i, j, status(MPI_STATUS_SIZE) character (len = 50) :: myfmt END SUBROUTINE AFprep
内容的提问来源于stack exchange,提问作者afernandezody
相关产品推荐
相关产品推荐

