Fortran函数字符参数长度是否隐式传递?属标准还是编译器实现?
Fortran与Python ctypes交互的标准性疑问
核心疑问
你提到的StackOverflow回答里的三个行为:参数按引用传递、字符数组非空终止、可变长度字符串的隐式长度参数按长整型值传递,需要区分哪些是Fortran标准规定,哪些是编译器特定实现,同时想确认示例中Python调用Fortran字符串函数时额外传入长度参数的方式是否跨编译器通用。
标准与编译器实现的边界
- 参数按引用传递:这是Fortran标准的核心规定。Fortran的默认参数传递方式为传引用(更准确说是参数关联,效果等价于传引用),所有标量、数组、字符串参数默认都按此方式传递,除非显式用
VALUE属性指定传值。 - 字符数组非空终止:这属于Fortran标准要求。Fortran字符串是自带长度属性的类型,无需依赖末尾空字符标识长度,和C风格空终止字符串的设计逻辑完全不同。
- 可变长度字符串的隐式长度参数:这不属于Fortran标准,是编译器调用约定(ABI)的特定实现。Fortran标准仅规定了
character(len=*)的语义,并未强制要求底层传递长度的方式——不同编译器可能采用不同策略:有的将长度作为额外参数按值传递(位置可能在参数列表开头或末尾),有的会把长度与字符串指针打包成结构体传递。
示例代码的跨编译器通用性
你给出的示例中,Python调用时额外传入长度参数的行为无法保证跨编译器通用:
- 在gfortran、ifort/ifx这类主流编译器中,确实会将
character(len=*)的长度作为额外长整型参数按值传递,且通常放在参数列表末尾,所以你的示例代码在这些编译器环境下能正常运行。 - 但小众或旧版本编译器可能采用不同ABI:比如有的会把长度参数放在所有参数前面,有的使用
int而非long类型,甚至会将字符串指针与长度封装成复合类型传递。 - 此外,Fortran编译器导出的函数名也有差异:gfortran默认给函数名加下划线(如
prnt变为prnt_),而ifort默认可能不加,这也会影响Python调用时的函数名写法。
示例代码
Fortran函数
function prnt(s) ! byref(s), byval(length) [long int, implicit] character(len=*):: s ! variable length input logical :: prnt write(*, "(A)") s ! formatted, to remove initial space prnt = .true. end function prnt
Python调用代码
from ctypes import * test = CDLL('./test.so') test.prnt_.argtypes = [c_char_p, c_long] s = 'Mary had a little lamb' test.prnt_(s, len(s)) # 输出:Mary had a little lamb 1
Fortran标准的查询方法
- 可从ISO官方购买正式的Fortran标准文档(如Fortran 2018),但需付费。
- 查看主流编译器厂商的文档,比如GCC、Intel的Fortran文档会明确标注哪些行为符合标准,哪些是编译器扩展。
- 参考Fortran语言委员会发布的免费标准草案,这些草案内容与正式标准几乎一致,足够日常开发参考。
内容的提问来源于stack exchange,提问作者EMiller
相关产品推荐
相关产品推荐

