6

如果我有这个代码

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 规范的情况下,我怎样才能使这个东西工作?是否必须声明一个具有相同长度的中间变量并在调用时传递它?

4

3 回答 3

8

标准语言可能很难理解。我读到@kemiisto 引用的条款要​​求长度(dummy arg) <= length(实际参数)。这里的长度(dummy arg) = 20length (actual arg) = 4,所以长度(dummy arg) > length (actual arg),这是从句不允许的。该子句谈到截断实际以匹配虚拟,如果需要,而不是用空格填充它。

如果您将代码替换character(len = 20)character(len = *) 是否存在问题,因为您不想修改虚拟参数规范的长度?

于 2011-01-25T04:16:21.663 回答
2

在我看来,这就像标准的合规行为。

Fortran 2003, 12.4.1.2 与虚拟数据对象关联的实际参数

如果标量虚拟参数是默认字符类型,则虚拟参数的长度 len 应小于或等于实际参数的长度。虚拟参数与实际参数最左边的 len 个字符相关联。

但是 gfortran 只是发出警告消息

警告:实际参数的字符长度短于 (1) 处的虚拟参数“名称”(4/20)

似乎英特尔 Fortran 编译器在这方面更符合标准。所以中间变量可能是唯一的选择。

或者实际上只是声明一个变量是一种选择,因为您的代码中没有变量。你有字面常量。无论如何,硬编码值都不是一个好主意。=)

于 2011-01-24T11:18:33.873 回答
2

发生此错误的原因是您的方法被允许读取/写入最多len=20字符到 dummy argument name。您的字符串文字小于此数量,并且您的编译器正在提醒您注意这一事实。即使声明了它,intent(in)您也可以读取超出实际参数长度并导致访问冲突等。

您可能应该坚持len=*使用虚拟参数并使用len,或者len_trim在确定可以安全读取/写入多少个字符时。

或者,如果您必须保留len=20,则应使用用于将值传递给该方法的临时变量。或者更丑的东西"hello"//repeat(" ", 15)

于 2011-02-03T17:12:21.117 回答