分配零大小的数组并在数组构造函数中使用

时间:2016-02-07 06:41:19

标签: arrays fortran allocation

在下面的代码中,我试图分配一个大小为0的空数组,然后使用自动重新分配添加更多元素:

integer, allocatable :: a(:)

allocate( a(0) )        ! Line 1
print *, size( a )
print *, "a(:) = ", a

a = [ a, 1 ]
print *, "a(:) = ", a

a = [ a, 2 ]
print *, "a(:) = ", a

!! Error
! a = []
! a = [ integer :: ]

此代码给出了预期的结果(例如,使用gfortran或ifort -assume realloc_lhs)

           0
 a(:) = 
 a(:) =            1
 a(:) =            1           2

这里我有三个问题:

  • 首先,可以分配零大小的数组,例如allocate( a( 0 ) )
  • 如果省略这样的显式分配,a(:)会自动初始化为零大小的数组吗? (实际上,即使我将第1行注释掉,代码似乎也能正常工作。)
  • 在像a = [a, 1]这样的数组构造函数中包含零大小的数组是没有问题的吗? (我也尝试使用像a = []a = [integer::]这样的空数组构造函数,但它们没有编译,因此似乎不被允许。)

修改

如果我在上面的代码中取消注释a = [],gfortran5.3会给出错误消息:

Error: Empty array constructor at (1) is not allowed

但是,如果我只取消注释行a = [ integer :: ],那么它没有问题!因为我最初同时取消了这两行,我误解了两种方式都是非法的,但实际上后者似乎没问题(请参阅@francescalus答案)。

2 个答案:

答案 0 :(得分:7)

1是的。 Fortran很酷,有0个大小的阵列。

2 a(:)不是数组,而是 array-section (虽然它包含整个数组)。自动重新分配未定义为对数组部分起作用,因此

allocate(a(0))
a(:) = [1 2 3]

不起作用。在我的测试中,代码已编译并执行,但a的大小为0

如果a = [a,1]之前没有分配a(0-或任何其他大小),代码allocate(a(0)) a = [a, 1] 是否应该起作用我对标准的解读是这不是标准的符合性你的编译器(我的)也是错误的。我希望这是我对标准的误读。也许其他人会来并正确解释。

3是

{{1}}

很好,它符合标准并按照您的预期工作。正如您所注意到的,在自动分配中不允许使用空数组构造函数

答案 1 :(得分:4)

High Performance Mark's answer涵盖了大部分内容,但还有更多要添加(或以不同方式重述)。关于a是否"初始化为零大小的数组",它不是,您可以看到更多详细信息in another question。请注意,特别是a最初未定义(和未分配)。

正如您的其他答案所述,a(:)是一个数组部分,无法在内部赋值上自动分配。或许值得注意的是,这是因为a(:)没有allocatable属性。这有其他影响,例如不允许它与具有该属性的伪参数相关联。

在高级别,是的,零大小的数组很好(再次,请参阅链接的问题,其中零大小和未分配之间存在有意义的差异)。使用该allocate语句并在后续数组构造函数中使用的方法是完全合理的。

但是,为了支持High Performance Mark的答案,不允许在数组构造函数中使用未分配的数组:可能不会引用未分配的变量。

构建一个零大小的数组:可以构造零大小的数组,并且对于可分配变量的内部赋值中使用的零大小数组没有什么特别的。

构造数组时,必须知道数组的类型(和类型参数)。使用数组构造函数(例如[a,1](假设a是默认类型的整数))此数组是默认类型的整数。编译器如何知道[]的类型/参数?

它不能,这就是为什么零大小数组的数组构造函数的语法就像你拥有它一样:[integer::]是一个(rank-1)零大小的数组构造函数默认类型的整数数组。

在Fortran 2008中,您可以将此语法看作R468,R469(4.8),类似可以在Fortran 2003中找到。

最后,对于零大小的数组构造函数还有另一种方法:

integer i
print*, [(i, i=1,0)]
end