使用错误类型的参数调用外部 Fortran 函数时会发生什么?

What happens when calling external an Fortran function with the wrong type of arguments?

如果您在文件中(而不是在模块中)有一个独立的函数,并且您使用单精度调用它,而它需要一个双精度数:

main.f90 :

program main

  call test(1.0)
end program main

test.f90:

subroutine test(a)
    double precision :: a
    print *, "a", a
end subroutine

在这种情况下,编译器"casts"如何从单精度到双精度? 使用浮点格式,我希望这些位在转换期间保持不变,但会附加额外的零。即:

1 = 0 01111111 00000000000000000000000 in single-precision

我希望最终值为 2^(-7):

0 01111111000 0000000000000000000000000000000000000000000000000000 in double precision

令人惊讶的是,对于 gfortran 6.4.0,最终值为 5.2635442471208903E-315。

我猜编译器 "casts" 根据字节顺序。如果你在左边放零,你会得到:

0 00000000000 0000000000000000000000111111100000000000000000000000

即 5.2635442471208903E-315。您可以通过在编译时强制字节顺序来检查。

编译器不进行转换。你写的不是Fortran.

在主程序中,子例程test 有一个隐式接口。本质上,编译器对此一无所知,只知道它是一个子程序。您还告诉它它有一个(默认的)真实参数。

在引用子例程时提供正确的参数类型和种类是您的责任,而不是编译器的责任。你在那里失败了,所以你没有兼容的 Fortran 程序。 Fortran 编译器不欠你什么。

您将观察到的内容取决于 Fortran 处理器的实现细节。该子例程需要一个双精度参数,并且没有理由相信它有任何其他参数。不管是有copy-in/copy-out还是某些地址传1,内存的解释都会不匹配。在伪参数中,除了与实际参数的默认实数对应的字节外,所有字节都是 "junk".

如果您在主程序中为子例程提供显式接口,仍然不会进行转换,但编译器会注意到不匹配。同样,即使存在隐式接口,某些编译器(可能具有某些编译标志)也会进行一些检查。


1 有关可能的传递引用的详细信息,请参阅 user5713492 的评论。