【问题标题】:Fortran Pointer arithmeticFortran 指针算法
【发布时间】:2013-10-17 19:54:49
【问题描述】:

这是我的第一个问题帖子......请不要残忍。

我的问题如下。我想将 fortran 指针分配为表达式。我认为通过简单的 fortran 技术是不可能的。但由于新的 fortran 版本似乎提供了处理 C 和 C++ 中使用的东西的方法(如 c_ptr 和 c_f_pointer ... ),也许有人知道解决我的问题的方法。 (我并不真正了解 C,但我读到 C 中可以使用指针运算) 为了让事情更清楚,这是我立即想到但不起作用的代码:

program pointer

real(8),target :: a
real(8),pointer :: b

b=>a*2.0d0  ! b=>a is of course working

do i=1,10
   a=dble(i)*2.0d0
   write(*,*)b
end do

end program

我知道有办法解决这个问题,但在实际程序中,我想到的所有这些都会导致更长的计算时间和/或相当复杂的代码。

非常感谢,提前!

最好的,彼得

【问题讨论】:

  • 不确定你要做什么,但在像 c 这样允许指针算术的语言中,算术只是加法/减法。 “算术”对内存地址进行运算,因此pointertoa + 1 会产生一个指针,指向 a 之后的下一个内存位置中的任何内容。我不认为这在 fortran 中是可能的,但无论如何你的乘法没有意义。
  • 感谢您使算术清晰。我尝试做的是以下内容。我有一个取决于许多输入变量的程序,其中的一个将在 do 循环内进行更改。但这取决于输入,改变哪一个。然而,循环结构总是相同的,并且参数存储在模块中,以便在大量子程序中可用。现在我想在参数读取部分之后编写一些案例构造,以告诉程序的其余部分哪个是要在循环内改变的参数,并且在循环中我有一个占位符(这里是 a)。
  • 如果占位符对每个参数遵循相同的表达式,一切都会完美运行。不幸的是,它没有。当然,我可以在每个点上写一个 if 子句,在哪里使用它,但是程序开头的单个决策点看起来更好,更受控制(在我自己或必须使用的人犯错误的情况下)未来的代码)并且通过计算时间更快。很抱歉回答太长,但你问我要做什么。
  • 将您的“我正在尝试做的事情”描述合并到问题本身中。对于那些试图准确理解您要问什么以及您要做什么的人来说,这种背景很重要!
  • 对不起,我的目标是尽可能简短。

标签: pointers fortran


【解决方案1】:

来自Michael Metcalf

指针是具有 POINTER 属性的变量;它们不是一种独特的数据类型(因此不可能有“指针算术”)。

它们在概念上是一个描述符,列出了指针可能指向的对象(目标)的属性,以及目标的地址(如果有的话)。在分配或以其他方式关联之前,它们没有关联的存储空间(通过指针分配,见下文):

所以你对b=>a*2 的想法不起作用,因为b分配a,而不是a

【讨论】:

    【解决方案2】:

    表达式,一般来说(有两个半非常重要的例外),不是有效的指针目标。表达式的求值(通常)产生一个值,而不是一个对象。

    (例外情况与整体表达式导致对具有数据指针结果的函数的引用的情况有关 - 在这种情况下,表达式可以在指针赋值语句的右侧使用,或者作为实际的过程引用中的参数对应于指针虚拟参数或[可能 - 仅限 F2008] 在可能需要变量的任何上下文中,例如普通赋值语句的左侧。但是您的表达式不会导致这样一个函数参考,我认为用例与你不想做的事情无关。)

    我认为您希望 b 的值随着 a 的“基础”值的变化而变化,按照初始表达式的形式。除了有效指针目标问题之外,这还需要与语言的基本原则之一相反的行为(实际上是大多数语言) - 表达式的评估在表达式评估时使用其初级的值 - 这些初级的后续更改确实不会导致历史评估值发生变化。

    相反,请考虑编写一个基于 a 计算 b 的函数。

    program pointer
      IMPLICIT NONE
      real(8) :: a
      do i=1,10
        a=dble(i)*2.0d0
        write(*,*) b(a)
      end do
    contains
      function b(x)
        real(kind(a)), intent(in) :: x
        real(kind(a)) :: b
        b = 2.0d0 * x
      end function b
    end program
    

    【讨论】:

    • 是的,谢谢,但这并不能解决问题。问题在上面的 cmets 中有描述。
    • 您所描述的内容可以很容易地使用过程指针来解决。
    • 嗯,我不完全确定你的意思。但我想它有点接近我在下面发布的内容。也许你有一个改进我已经有的建议。 :-) 我很确定,这是可能的。无论如何,感谢您的帮助。如果您回答我,请不要介意我只能在几个小时内回答,因为这里已经是 0:18。最佳彼得
    【解决方案3】:

    更新:我越来越接近我想要的(对于那些感兴趣的人):

    module test
    
    real,target :: a
    real, pointer :: c
    
    abstract interface
       function func()
          real :: func
       end function func
    end interface
    
    procedure (func), pointer :: f => null ()
    
    contains
    
    function f1()
      real,target :: f1
    
      c=>a
      f1 = 2.0*c
    
      return
    end function f1
    
    end module
    
    program test_func_ptrs
    
    use test
    
    implicit none
    
    integer::i
    
    f=>f1
    
    do i=1,10
       a=real(i)*2.0
       write(*,*)f()
    end do
    
    end program test_func_ptrs
    

    如果我能找到一种方法来避免虚拟参数(至少在我调用 f 时),我会完全满意。

    附加信息:重点是我想在开始循环之前定义不同的函数 f1 和 deside,f 将在循环内部(取决于任何输入)。

    【讨论】:

      【解决方案4】:

      从指针计算地址偏移量的意义上来说,指针算术在 Fortran 中是不允许的。指针算法很容易导致内存错误,Fortran 的作者认为没有必要。 (可以通过与 C 互操作性的后门来实现。)

      Fortran 中的指针对于将过程作为参数传递、设置数据结构(例如链表(例如,How can I implement a linked list in fortran 2003-2008)等)非常有用。

      【讨论】:

        猜你喜欢
        • 2022-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多