错误:具有非零等级的部分引用右侧的部分名称具有 ALLOCATABLE 属性

Posted

技术标签:

【中文标题】错误:具有非零等级的部分引用右侧的部分名称具有 ALLOCATABLE 属性【英文标题】:Error: The part-name to the right of a part-ref with nonzero rank has the ALLOCATABLE attribute 【发布时间】:2015-01-26 19:49:48 【问题描述】:

我想使用子例程 sum_real 访问数组派生类型中的数组元素。即:对所有人的权重中的第一个条目求和。

type my_type
   real, dimension(:), allocatable :: weight
   real :: total_weight
end type my_type

type (my_type), dimension (:), allocatable :: people
type (my_type) :: answer

allocate (people (2))
allocate (people (1)%weight(2))
allocate (people (2)%weight(2))

people (1) % weight(1) = 1
people (2) % weight(1) = 1
people (1) % weight(2) = 3
people (2) % weight(2) = 3

call sum_real ( people (:) % weight(1), answer % total_weight )

我想要做的类似于在Array of derived type: select entry 中找到的答案,除了我有一个以数组派生类型而不是单个元素分配的数组。

但是,我得到一个编译器错误:

error #7828: The part-name to the right of a part-ref with nonzero rank has the ALLOCATABLE attribute (6.1.2).   [WEIGHT]

【问题讨论】:

权重组件总是大小为 2 吗? 【参考方案1】:

如果您的组件是可分配的,那么您尝试的操作是不可能的。引用(6.1.2)实际上是对官方标准文档的引用,禁止这样做。

原因很简单,可分配的组件(标量或数组)存储在与派生类型本身不同的内存部分。因此,如果你写

sum(people%total_weight)

people%total_weight = 0

没问题,total_weight 不可分配,它存储在派生类型中,编译器只是进入一个简单的循环并将一个接一个的字段设置为零。你可以预先知道每个%totalweight的地址。

另一方面

sum(people%weight)

people%weight = 0

每个%weight 都存储在其他地方,您没有任何简单的公式可以计算每个%weight(i) 的位置。

如果可能的话,解决方案是固定数组的大小

real, dimension(2) :: weight

或使用 do 循环

s = 0
do i = 1, size(people)
  S = S + sum(people(i)%weight)
end do

【讨论】:

【参考方案2】:

如果你有一个 F2003 编译器,并且组件数组的边界对于特定的父数组对象是相同的,则由常量表达式指定的大小的第三种方法/使用 VladimirF 指定的 do 循环方法是参数化输入。

type my_type(n)        ! This type has one parameter - n
  integer, len :: n    ! The parameter n is a length parameter.
  real :: weight(n)    ! This component depends on that parameter.
end type my_type

type (my_type(:)), dimension(:), allocatable :: people

! This integer is the size of the people component.  Because 
! people is allocatable it can be determined at runtime.
number_of_people = 2

! This integer is the size of the weight component that we want 
! in the array people.  Other arrays and scalars of type 
! my_type can have different sizes for that component.  
! Because people is allocatable this can be determined at 
! runtime.
number_of_weights = 2

allocate( my_type(number_of_weights) :: people(number_of_people) )

! Define people%weight here.
people(1)%weight(1) = 1
...

! Using sum intrinsic for the sake of example
do i = 1, people%n
  ! The argument to sum is an array section.
  print *, sum(people%weight(i))
  !                 ^        ^ Reference to an element of a component
  !                 | Reference to the entire people array
end do

参数化类型数组中的每个元素都具有相同的类型参数,因此people 中的每个weight 组件具有相同的边界,因此people%weight 等引用成为“常规”。

使用这种方法(或恒定组件大小规范方法)的代码仍然必须遵循组件引用的限制,即只有一部分引用可以具有非零等级(您不能将 people%weight 作为整体,因为人和重量分量都排名第一)。

在可分配组件的情况下,某些元素中的某些组件可能不会被分配,并且在分配它们的位置,组件可能具有不同的边界,因此在概念上很难跨数组元素对组件中的数据进行“常规”引用。

【讨论】:

以上是关于错误:具有非零等级的部分引用右侧的部分名称具有 ALLOCATABLE 属性的主要内容,如果未能解决你的问题,请参考以下文章

具有大部分半加性事实的建模场景

具有快速滚动和字母部分索引的 Android ListView

在 Pandas Dataframe 中获取具有非零列的前 11 行

在具有相同行值名称的部分中显示行

具有自定义高度的 NSTableView 部分横幅列

mysql外键仅引用复合主键的一部分