Fortran和c在源代码接口和编译方式上的细微差别

Fortran和c在源代码接口和编译方式上的细微差别,c,interface,module,fortran,header-files,C,Interface,Module,Fortran,Header Files,这两种语言都可以使单个程序/库跨越多个文件。C语言使用include语句,使用显式创建的头文件,而Fortran让编译器从单个模块生成接口。如果我误解了任何一种语言是如何编译其源代码的,请事先原谅我 在c/c++程序中,您通常创建包含源代码的.c文件和包含代码接口的.h文件,以便其他源文件可以预测源代码中的内容,然后将这些内容一起编译成库、对象文件等 在Fortran程序90+中,您可以将代码放入单独的模块中,而不是为每个模块显式地编写头/接口文件,编译器将为它们生成接口,并将它们放入单独的二进

这两种语言都可以使单个程序/库跨越多个文件。C语言使用include语句,使用显式创建的头文件,而Fortran让编译器从单个模块生成接口。如果我误解了任何一种语言是如何编译其源代码的,请事先原谅我

在c/c++程序中,您通常创建包含源代码的.c文件和包含代码接口的.h文件,以便其他源文件可以预测源代码中的内容,然后将这些内容一起编译成库、对象文件等

在Fortran程序90+中,您可以将代码放入单独的模块中,而不是为每个模块显式地编写头/接口文件,编译器将为它们生成接口,并将它们放入单独的二进制文件.mod文件以及编译的对象文件中。创建库、对象文件等需要将它们编译/链接在一起


为什么这些语言在编译接口的方式上有如此细微的差别?这仅仅是两种语言悠久历史的产物吗

C远不如你说的那么有条理。头文件的使用纯粹是一种惯例;预处理器允许任意的文本包含,并且语言中没有接口和实现的原则划分

简单的事实是,链接C程序的独立翻译单元是不可检查或不安全的;这是你的责任,你链接的各个部分实际上是结合在一起的

在早期的C语言中,函数声明可以是隐含的,并且函数参数根本不被检查。因此,您可以在代码中插入一个调用foo1、2、3,这意味着函数int foo的声明,并且参数需要匹配最终函数定义将使用的参数


C中使头文件有用的两个关键特性是声明和函数原型。如果您同意在使用编译器可能警告您的功能之前始终需要明确的函数声明,那么您可以在头文件中提供该声明,这样链接就更有可能适合。函数原型是声明概念的扩展,声明自动在调用站点用函数定义中的参数修复参数,因此如果您选择使用所有这些功能,您可以通过头文件很好地记录您的函数调用接口。但这一切纯粹是惯例

C远不如你说的那么有条理。头文件的使用纯粹是一种惯例;预处理器允许任意的文本包含,并且语言中没有接口和实现的原则划分

简单的事实是,链接C程序的独立翻译单元是不可检查或不安全的;这是你的责任,你链接的各个部分实际上是结合在一起的

在早期的C语言中,函数声明可以是隐含的,并且函数参数根本不被检查。因此,您可以在代码中插入一个调用foo1、2、3,这意味着函数int foo的声明,并且参数需要匹配最终函数定义将使用的参数


C中使头文件有用的两个关键特性是声明和函数原型。如果您同意在使用编译器可能警告您的功能之前始终需要明确的函数声明,那么您可以在头文件中提供该声明,这样链接就更有可能适合。函数原型是声明概念的扩展,声明自动在调用站点用函数定义中的参数修复参数,因此如果您选择使用所有这些功能,您可以通过头文件很好地记录您的函数调用接口。但这一切纯粹是惯例

Fortran标准没有提到.mod文件。如果不同的语言不能使用不同的方法来完成相同的事情,我们会有多少种语言?是的,它主要是每种语言发展历史的产物。和其他语言一样,比如说,Java做他们自己的事情。没有理由期望两种不同的语言在编译和链接多个源文件中的代码时使用相同的约定。为什么您期望不同的语言具有相同的功能?我不期望@Olaf语言有任何功能,我只是注意到了差异,并想知道这背后是否有原因。我想在实践中,有很多方法可以剥猫的皮。.Fortran标准没有提到.mod文件。如果不同的语言不能使用不同的方法来完成相同的事情,我们会有多少种语言?是的,它主要是每种语言发展的产物
历史和其他语言一样,比如说,Java做他们自己的事情。没有理由期望两种不同的语言在编译和链接多个源文件中的代码时使用相同的约定。为什么您期望不同的语言具有相同的功能?我不期望@Olaf语言有任何功能,我只是注意到了差异,并想知道这背后是否有原因。我想在实践中,有很多方法可以剥猫皮。实际上,现代C语言在使用C99之前需要函数声明。@Olaf:是的,但您仍然可以在本地执行该声明,如extern f;。外部声明实际上不是本地的。无论如何,您是对的,仍然允许使用非原型声明器。它刚刚在C11中成为过时功能,不确定它是否已经在C99中。在另一点上,委员会太三心二意了,使语言更安全。我敢打赌,即使是从C2x上,他们也不会删除这个遗留问题。@Olaf:我的意思是在本地,不使用传统的模块接口,也不使用特殊的外部链接。这是一种编程方法,它非常快速,容易,也就是懒惰,允许快速原型化,而且在C的早期使用相当广泛。事实上,C++的进化面临着对原型强制的严重反对。这就是我在第一次尝试后更改为Modula-2的原因之一,因为我最初来自Pascal:。这可能是C++早期的一些反对意见,但是从我对C++ 11的了解,标准的第二个版本在过去的几十年里发生了很大的变化。我仍然怀念这个来自沃思语言的干净接口。Oberon-2有一个非常好的方法来自动生成接口——实际上是现代的C,因为C99在使用它们之前需要函数声明。@Olaf:是的,但您仍然可以在本地执行该声明,如extern f;。外部声明实际上不是本地的。无论如何,您是对的,仍然允许使用非原型声明器。它刚刚在C11中成为过时功能,不确定它是否已经在C99中。在另一点上,委员会太三心二意了,使语言更安全。我敢打赌,即使是从C2x上,他们也不会删除这个遗留问题。@Olaf:我的意思是在本地,不使用传统的模块接口,也不使用特殊的外部链接。这是一种编程方法,它非常快速,容易,也就是懒惰,允许快速原型化,而且在C的早期使用相当广泛。事实上,C++的进化面临着对原型强制的严重反对。这就是我在第一次尝试后更改为Modula-2的原因之一,因为我最初来自Pascal:。这可能是C++早期的一些反对意见,但是从我对C++ 11的了解,标准的第二个版本在过去的几十年里发生了很大的变化。我仍然怀念Wirth languages Oberon-2的干净界面,它有一种非常好的自动生成界面的方法