如果我有这段代码
module test
contains
subroutine xx(name)
character(len=20), intent(in), optional :: name
if (present(name)) then
print *, name
else
print *, "foo"
endif
end subroutine
end module
program x
use test
call xx()
call xx("foo2")
end program
它不会编译,因为“foo2”的长度不是20,编译器会抱怨
test.f90(17): error #7938: Character length argument mismatch. ['foo2']
call xx("foo2")
-----------^
如何在不修改子程序dummy len规范的情况下使这个东西工作?是否必须使用相同的长度声明一个中间变量并在调用时传递它?
答案 0 :(得分:7)
标准语言很难理解。我读了@kemiisto引用的条款,要求长度(dummy arg) <= length
(实际arg)。此处长度为(dummy arg) = 20
和length (actual arg) = 4
,因此长度为(dummy arg) > length (actual arg)
,该条款不允许这样做。该子句讨论截断实际以匹配虚拟,如果需要,不用空格填充它。
如果用character(len = 20)
替换character(len = *)
,代码将有效。因为您不想修改伪参数规范的长度,所以有问题吗?
答案 1 :(得分:2)
对我而言似乎符合标准的行为。
Fortran 2003,12.4.1.2与虚拟数据对象相关的实际参数
如果标量伪参数是类型的 默认字符,长度为len 伪论证应小于 或等于实际的长度 论点。虚拟参数变为 与最左边的len相关联 实际论证的字符。
然而,gfortran只是发出警告信息
警告:实际参数的字符长度短于虚拟参数'name'(4/20)(1)
在这方面,英特尔Fortran编译器似乎更符合标准。所以中间变量可能是唯一的选择。
或者实际上只是声明一个变量是选项,因为你的代码中没有变量。你有文字常数。无论如何,硬编码值不是一个好主意。 =)
答案 2 :(得分:1)
发生此错误的原因是允许您的方法将最多len=20
个字符读/写到伪参数name
。你的字符串文字小于这个数量,你的编译器会提醒你这个事实。即使声明为intent(in)
,您也可以读取超出实际参数长度并导致访问冲突等。
你应该坚持len=*
使用伪参数,并在确定读/写安全字符数时使用len
或len_trim
。
或者,如果必须保留len=20
,则应使用用于将值传递到该方法的临时变量。或者像"hello"//repeat(" ", 15)
那样更加丑陋。