我在一个看起来像这样的模块中有一个函数(如果有人有兴趣,它是this function)
MODULE MYMODULE
IMPLICIT NONE
! Some random stuff
CONTAINS
CHARACTER*255 FUNCTION strtok ( source_string, delimiters )
[...]
END FUNCTION strtok
SUBROUTINE DO_SOMETHING ( )
CHARACTER(LEN=255) :: strtok
[...] !
END SUBROUTINE DO_SOMETHING
END MODULE MYMODULE
strtok
函数是C的字符串标记化器的一个版本,我将在DO_SOMETHING
子例程中使用此函数。我需要定义strtok
,否则gfortran会抱怨它没有被定义。但是,如果我这样做,并编译我的代码并将其链接到主程序,链接器会抱怨对strtok_
的未定义引用。我不知道为什么会这样,因为它们都在同一个模块中,应该是可见的。同一模块中的其他功能和子程序没有此问题。这是否与这个字符* - 回归功能有关?
答案 0 :(得分:4)
在下文中,我将使用下面的完整示例(您可以编译和链接来尝试)来解释:
module mymodule
contains
integer function foo ()
foo = 1
end function
integer function bar ()
integer :: foo
bar = foo()
end function
end module
program test
use mymodule
print *, bar()
end
在函数bar
的代码中,声明integer :: foo
严格等同于:
integer, external :: foo
因此,在bar
的代码中,您明确说明:
“可能已经有了名字的象征
foo
您可以访问,但从现在开始 当我使用它时,我的意思是它是一个 此名称的外部功能“
所以,这是有效的代码,编译器只希望你提供一个名为external
的{{1}}函数。因为你没有(模块功能不是外部的),它无法链接。您可以通过添加以下代码(不在模块中,仅在同一文件的末尾)提供外部foo
功能:
foo
如果添加此函数体,则代码将编译,输出将为integer function foo ()
foo = 42
end function
(因为调用外部函数,而不是模块函数)。
另外值得注意的是,如果您在42
的代码中注释掉integer :: foo
行,则符号bar
将解析为模块函数,无论您是否提供该模块函数一个名为foo
的外部函数(因此,输出将为foo
)。
结论:不是编译器错误,而是滥用语言的旧功能(外部声明)。说实话,我认为最好明确标记你的1
声明,这至少会在这里强调这个问题。
答案 1 :(得分:1)
从您发布的不完整源代码判断,我认为这可能是违规行:
CHARACTER(LEN=255) :: strtok
由于子例程DO_SOMETHING
和函数strtok
在同一模块中,因此它们会自动了解彼此的定义(它们具有显式接口)。这意味着不仅没有必要在strtok
内重新声明函数DO_SOMETHING
的类型,但实际发生的是该行在子例程范围内声明了一个名为strtok
的新字符变量DO_SOMETHING
,使用相同的名称覆盖模块函数。
基本上,在子例程中,标识符strtok
引用变量,因此当您尝试通过该名称引用函数时,编译器不知道它。
嗯,既然我正在写这个,我开始认为这应该给出编译时错误,而不是链接错误。尽管如此,尝试评论我提到的那条线并试一试可能是值得的。