Arrays 传递比实际更小的数组
在下面的代码中,我声明了一个包含20个元素的数组Arrays 传递比实际更小的数组,arrays,fortran,Arrays,Fortran,在下面的代码中,我声明了一个包含20个元素的数组mass。当传递到子程序foo时,foo被告知mass只有10个元素。但是,我仍然可以访问第20个元素。我的问题是: 为什么我可以将数组传递给子例程并告诉子例程数组的错误大小 为什么我仍然可以访问第20个元素,即使子例程认为它只有10个元素 在foo中,我对数组中第20个元素所做的任何更改是否会保留在数组中,就像foo知道数组的正确大小一样 代码如下: program test implicit none integer num2
mass
。当传递到子程序foo
时,foo
被告知mass
只有10个元素。但是,我仍然可以访问第20个元素。我的问题是:
- 为什么我可以将数组传递给子例程并告诉子例程数组的错误大小
- 为什么我仍然可以访问第20个元素,即使子例程认为它只有10个元素
- 在
中,我对数组中第20个元素所做的任何更改是否会保留在数组中,就像foo
知道数组的正确大小一样foo
program test
implicit none
integer num2,i
real*8 mass(20)
num2=10
do i = 1,num
mass(i) = 1.d0
end do
call foo(num2,mass)
end
subroutine foo(num2,mass)
integer num2
real*8 mass(num2)
write(*,"(A20,E15.9)") "first one:",mass(1)
write(*,"(A20,E15.9)") "tenth one:",mass(10)
write(*,"(A20,E15.9)") "twentieth one:",mass(20)
continue
end
注意:这种子例程被告知数组大小错误的情况是我在其他人的代码中遇到的,我正试图修改以供自己使用 为什么我可以将数组传递给子例程,并告诉子例程数组的大小错误?
因为Fortran允许您使用数组的一部分
为什么我仍然可以访问第20个元素,即使子例程认为它只有10个元素?
因为1)数组元素在内存中是连续的,所以索引到达第20个元素,2)Fortran生成的程序通常不会检查编程是否正在执行无效的数组订阅。大多数编译器都有插入此类检查的选项,例如gfortran的-fcheck=bounds
或-fcheck=all
我在foo中对数组中的第20个元素所做的任何更改是否会保留在数组中,就像foo知道数组的正确大小一样?
对如果您这样做了,并且原始数组没有20个元素,那么您将更改一个不相关的内存位置,结果会很糟糕。在您的问题背后有一些误解,我将在本答案中加以说明。本文给出了一些实际意义 你说你声明了一个包含二十个元素的数组
mass
,但是foo
被告知它只有十个元素。这是不对的
实际上,您拥有两个不同的实体:主程序中的数组mass
,包含二十个元素,以及子例程foo
中大小为十的数组(也称为mass
)
“传递”是在这两个实体之间建立关联(所谓的参数关联)。主程序中名为mass
的数组是子例程中的实际参数,子例程中名为mass
的数组是伪参数
伪参数是显式形状的数组,范围num2
(也是与主程序的num2
关联的参数)。伪参数的第一个num2
元素与实际参数的第一个num2
元素相关联。[这要求主程序中的数组中至少有num2
元素。]
那么,第一个问题的答案是什么
为什么我可以将数组传递给子例程并告诉子例程数组的错误大小
就是这样:您没有告诉它错误的大小,您只是说子例程中的数组对应于参数的第一个num2
元素
来到
为什么我仍然可以访问第20个元素,即使子例程认为它只有10个元素
这是一个编程错误。不允许使用大于数组范围的下标值。当您尝试此操作时会发生什么情况取决于编译器。正如另一个答案所说,这很可能只是访问(由于关联的实现方式)内存中与实际参数的大元素相对应的位置。但同样地,编译器可能会抱怨(尤其是那些检查所选编译选项的人),或者,如果传递是通过临时复制完成的,那么事情可能会崩溃。[后一种可能性不大。]
最后
我在foo中对数组中的第20个元素所做的任何更改是否会保留在数组中,就像foo知道数组的正确大小一样
这也是特定于实现的。没有正确的Fortran答案,因为您的程序不符合要求。与前一点一样,如果这是与实际参数的适当元素相对应的内存区域,并且没有进行边界检查,那么更改可能会持续。如果编译器选择进行复制,则可能会发生崩溃,或者在返回时会忽略边界之外的更改。[同样,后两个不太可能,因为这需要编译器“聪明”。也许您可以使用显式接口(例如,通过将子例程放置在模块中)。这样,您可以在运行时通过执行
size(array)
来检查数组的大小,您就不必担心被传递到错误大小的数组了。@EMiller,谢谢您的想法,也许我会这么做。不幸的是,这是一个由其他人编写的代码,有点大,我在这里描述的情况发生在很多地方。