【问题标题】:Passing parameter as parameter in Fortran-90?在 Fortran-90 中将参数作为参数传递?
【发布时间】:2015-12-09 18:53:27
【问题描述】:

假设我有一个子程序:

subroutine foo(x, Nx)
    implicit none
    integer, intent(IN) :: x
    integer, intent(IN) :: Nx

    select case(x)
        case (1)
            write(*,*) "Minimum value"
        case (Nx)
            write(*,*) "Maximum value"
        case default
            write(*,*) "Somewhere in-between"
    end select
end subroutine foo

假设我的驱动程序如下所示:

program main
    implicit none

    interface
        subroutine foo(x,Nx)
            integer, intent(IN)  :: x
            integer, intent(IN)  :: Nx
        end subroutine foo
    end interface

    integer, parameter :: Nx = 100
    integer :: x

    call foo(20, Nx)

end program main

上面的程序将无法编译,因为在子程序中,case (Nx) 无效。具体来说,ifort 16 给出以下错误:

错误 #6601:在 CASE 语句中,case-value 必须是常量表达式。

换句话说,即使 Nx 实际上通过intent(IN) 声明为子例程常量,它也必须是字面常量或integer 类型的parameter

有没有办法让 case 语句接受 Nx 作为我们知道的常量参数?有没有办法将Nx 声明为传入的parameter

我意识到在这个简单、简短的示例中,一个 if-then-elseif-else-end 块就足够了,但是我不知道这个问题的答案。 :-)

【问题讨论】:

  • 仅供参考,您在"Maximum value 之后缺少结束引号。并且可能是:: 中的integer, parameter Nx
  • 你能定义一个包含你的参数和子程序的模块吗?如果是这样,会有帮助吗?:)
  • 顺便说一句,你说“换句话说,即使 Nx 通过intent(IN)...有效地声明为子例程常量”。我认为问题在于 fortran 需要知道case在编译时,因此作为子例程常量是不够的。否则,我不明白为什么在不必指定任何常量属性的情况下即时找出值会伤害编译器。
  • @AndrasDeak:其他语言不要求 switch/select/case 构造具有编译时常量(它们通常不是!)。我承认语言规范,但我认为这更像是一个错误而不是一个功能。 (但我知道什么?!:-))我认为模块的想法可能会奏效(Personal ToDo:test this),尽管它不适合这个目的。
  • 重点是 case 结构通常可以实现为跳转表,而不是 if-else 分支。 C 具有相同的属性。

标签: parameters fortran fortran90 intel-fortran select-case


【解决方案1】:

您问是否有办法“接受 Nx 作为我们知道的常量参数?”。我们知道 Nx 构成一个常量表达式,我们确实知道它

Nx 成为常​​量表达式的唯一方法是让Nx 成为命名常量。作为一个命名常量与作为一个虚拟参数是不兼容的,即使是一个与参数相关联的参数,具有intent(in) 或没有intent 属性,具有命名常量。

从概念上讲,就主程序而言,子程序foo 是一个外部程序(有一个接口块)。这意味着人们会期望它被编译为一个独立的东西,在稍后阶段被链接。无论其最终用途如何,它都应该是有效的。 [也就是说,即使它不是外部过程,就语言规范而言,第一部分仍然适用。]

当然,如果您不想使用 if 构造重写它,还有其他方法可以在子例程中使用 Nx 命名常量。

【讨论】:

    【解决方案2】:

    只需使用 if 语句。子例程参数(您称为参数)当然不是参数(命名常量)。 intent(in) 并没有有效地 使它成为一个参数,它只是一个你不会改变它的承诺,但是有办法绕过它。 case 语句需要一个编译时常量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 2016-12-15
      相关资源
      最近更新 更多