Fortran Coder

查看: 1631|回复: 4

[求助] 编译问题

[复制链接]

37

帖子

11

主题

0

精华

专家

F 币
369 元
贡献
141 点
发表于 2023-8-6 19:18:39 | 显示全部楼层 |阅读模式
主函数和function写在同一文件中,参数类型和数量都是错的,但编译还是通过了,结果也算出来了。

[Fortran] 纯文本查看 复制代码
program main
    implicit none

    integer:: a=0, b=100
    integer:: func
    print*, func(a,b)

end

function func(arg)
    implicit none
    real,intent(in)::arg
    integer:: func
    func = arg + 1
end


编译器只是给出了警告,但还是能编译成功的。
我知道这是隐式接口的问题,但我不清楚具体发生了什么。请问:
1. 将 function 写在 program 的前面和写在 program 的后面有什么区别?
2. 将 function 和 program 写在不同的文件中编译和写在同一文件中编译有什么区别?
3. Fortran 的编译逻辑和 C 语言有什么不同吗?

-- gcc version 8.1.0

1995

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1481 元
贡献
636 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2023-8-6 20:06:56 | 显示全部楼层
这里面涉及到一些未定义行为。所以不同编译器可能表现不同。
我个人是不喜欢研究这些未定义行为的。
按规范的写,就可以了。不规范会有什么影响,我并不喜欢深究。

此外,我现在所有可执行代码,都放在module或主程序里。已经不再使用外部子程序

function 写在前面,可能利于某些编译器自动生成接口并检查接口是否一致(这句话并不是说编译器一定会去做接口检查)。让编译器给出警告或者直接拒绝。
其实一部分编译器就算你写在后面,也一样可以检查接口。有些编译器还可以设置,是否检查接口。

写在不同的文件里(在这个问题上),一般和写在后面是没什么区别的。

第三个问题太复杂了,没点时间专门去分析编译器源码并归纳总结,是回答不了的。

1995

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1481 元
贡献
636 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2023-8-6 20:22:03 | 显示全部楼层
不管是做为程序员,还是编译器的开发者。
都想尽了一切办法,让错误提前。
所谓错误提前,就是让错误尽可能的在以下4个阶段里更早的阶段被发现:

编译错误,链接错误,运行时错误,逻辑错误(运行结果不符合预期)

如果接口不一致,编译器也不做检查,那么错误就会是运行时错误,如果运行时库也不检查,那就是运行崩溃。
所以优秀的编译器才会在编译链接时主动的去检查接口。
但做为程序员,不能一味的指望编译器来发现。万一编译器不发现呢?

在你的案例中,既然你的编译器给你了警告,我想,实际它在处理的时候,应该是主动为你考虑并填补了。
例如,如果编译器什么都不处理,调用者压入2个参数的堆栈。但被调用者只使用了1个,并且清理堆栈顶的时候按1个去清理,那么会产生堆栈失衡,导致运行崩溃。
如果你的程序能正常运行,可能是你的编译器自动为你做了处理,例如舍弃了第二个参数未压入堆栈。
另一个可能的情况是,你使用的是64位编译器,用的 x64 fast call 调用协定。那么2个参数是放入寄存器的,多放了一个寄存器也没关系。不需要清理堆栈,也不会造成失衡。所以程序能够运行。

不管怎么样,能够运行只是偶然的。去研究为什么会偶然,去研究到底编译器中间做了什么非语法严格强制规定的措施?对一个普通的 Fortran 程序员,没有什么价值。

37

帖子

11

主题

0

精华

专家

F 币
369 元
贡献
141 点
 楼主| 发表于 2023-8-6 21:09:21 | 显示全部楼层
fcode 发表于 2023-8-6 20:22
不管是做为程序员,还是编译器的开发者。
都想尽了一切办法,让错误提前。
所谓错误提前,就是让错误尽可能 ...

感谢感谢!
以前用Matlab和C比较多。看见有的fortran函数是用内部过程,又看见有些代码是分开写的,比较混乱。
谢谢刘涛详细的解答

1995

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1481 元
贡献
636 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2023-8-7 08:44:20 | 显示全部楼层
把可以放入module的函数都放入module,就会强制检查接口是否一致(这是语法明确规定的)。
这样,你就不必用这个问题而纠结了。并且也符合现代 Fortran 代码的形式(说白了就是优雅)。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-7-21 10:08

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表