回 帖 发 新 帖 刷新版面

主题:[讨论]矢量下标作数组索引时的只读属性

最近在 debug 程序时得到了确认,花去了我几天的时间,实在有些不甘心。为避免诸位误入此类陷阱,特发帖说明。其实无论是 Intel 的 reference 还是 IBM 的线上文档都有说明,但在遇到这个问题之前谁又会注意到呢?:P

    program main
        implicit none
        integer, dimension(4) :: array

        array = 0
        call eval(array(2:), 3)
        print *, array(3)

        array = 0
        call eval(array((/2,3,4/)), 3)
        print *, array(3)

        stop
    end program

    subroutine eval(a, n)
        implicit none
        integer, intent(in) :: n
        integer, dimension(n) :: a

        a(2) = -1

        return
    end subroutine eval

以上为测试代码,如果遇到过这个问题的朋友,一看便知。

[quote][I]If you pass an array section with a vector subscript as an actual argument, the associated dummy argument must not be defined or redefined.[/I][/quote]
这是 IBM 线上文档对于矢量下标哑实传递的说明。用的是 must not be defined or redefined,所以我想这应该是个只读属性。正如上例中所示,即使 redefined,实参并无影响。

但如果不作子程序传递,直接赋值,比如:

array((/2,3,4/)) = -1

这是可行的。也即,只是哑实传递时才会有这个限制。对于 Intel 汇编不熟悉,不太清楚编译器是如何实现的。是直接抛弃还是在传递时作了复制操作?


另外,基于 gcc 4.5.3 的 gfortran 尚不支持 array((/1,3:4/)) 这种混合下标索引。

回复列表 (共17个回复)

11 楼

其实楼主可以考虑改成FUNCTION来返回数组这种方式来解决SUBROUTINE中修改无效的这种状态:)

当然,既然这样用了,那就代表我们是不记成本了:)

12 楼

谢谢楼主的提示!

一般情况下,我会把整个向量传过去,也即传首地址,然后在子程序中进行操作,当然你这样某些时候,比如不连续的时候是很方便的,就如cgl_lgs兄所说,不计成本的时候,写成function是不错的选择。
继续被cgl_lgs,yeg001,dongyuanxun的才华所拜倒!

13 楼

ls乃去屎

14 楼

哈哈

15 楼

呵呵

16 楼

董兄不带这么调情的:)

17 楼

Fortran 标准明确规定,矢量下标数组做实参,传给形参时,形参是 undefined。因此,楼主的程序本身就是一个 Bug,当形参用 intent 修饰时,编译器一般会给出一些警告之类的信息(这就是为什么 Fortran 90 之后一般推荐用 intent 修饰形参)。
还有一个大家讨论的问题,就是编译器是否用了临时内存,也就是 copy in / copy out, 这个当然有损程序的效率,请参考 The Fortran 2003 Handbook,上面颇有一些讨论,我们看过之后,对此类问题的讨论颇有高屋建瓴之感。

我来回复

您尚未登录,请登录后再回复。点此登录或注册