为什么ifort和gfortran之间有不同的行为?用ifort编译它返回false并且gfortran为true.我之前在自己的代码中遇到了这个问题并决定使用子程序,但最近的一个问题让我质疑这种行为.
function allocateArray(size)
integer, allocatable, dimension(:) :: allocateArray
integer size
allocate(allocateArray(size))
end function allocateArray
Run Code Online (Sandbox Code Playgroud)
从主程序
integer, allocatable, dimension(:) :: a
a = allocateArray(10)
print *, allocated(a)
Run Code Online (Sandbox Code Playgroud) 我想要一个数组从Fortran中的数组中删除某个索引值之后的所有行.这意味着如果数组的大小最初是p,它应该变为q,其中q是索引,之后将删除所有内容.
以下是相关的代码:
real(8), allocatable :: circlesx(:),circlesy(:)
allocate(circlesx(n**2-n))
allocate(circlesy(n**2-n))
do i=1,n-1
do j=i+1,n
call intersect2circles(stlo(i),stla(i),distance(i),stlo(j),stla(j),distance(j),ax,ay,bx,by,flag)
if (flag==0) then
circlesx(k)=ax
circlesy(k)=ay
circlesx(k+1)=bx
circlesy(k+1)=by
k=k+2
endif
enddo
enddo
Run Code Online (Sandbox Code Playgroud)
该标志基本上检查两个圆是否相交.因此,如果没有交集,没有值被分配给阵列circlesx和circlesy.我首先分配的数组的大小是n个圆=的最大交点数n^2-n.如果我不分配它,我会遇到分段错误.
重塑也没有用,虽然我可能在那里做错了.这给出了一个无法分类的陈述错误: -
reshape(circlesx,[ n**2-n-1 ])
Run Code Online (Sandbox Code Playgroud)
我希望圆圈数组的大小k-2在循环完成后更改为
所以我需要的是,如果n = 2,那么circlex和circley的大小为2,那么,
circlesx=[0,0]
.
.
some calculations
.
.
circlesx=[1.2,0] ! only one value has been allocated
.
.
reshape the array accordingly
.
.
circlesx=[1.2]
Run Code Online (Sandbox Code Playgroud)
在Fortran有什么办法吗?我正在使用f90文件扩展名并使用gfortran v7.3.0
如果我的编译器兼容Fortran 2003,我可以重新分配可分配变量或数组,而无需显式解除分配/分配过程,如Fortran 中分配时自动数组分配中所述。例如
integer, allocatable :: i(:)
i = [1,2,3]
i = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
与旧的(Fortran 90)方式相比:
if( allocated(i) ) deallocate(i)
allocate(i(3))
i = [1,2,3]
if( allocated(i) ) deallocate(i)
allocate(i(5))
i = [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
这种新技术有什么优点和缺点?这肯定是比旧方法更简洁的代码。但有理由选择旧方式吗?我在代码示例中仍然看到旧方法比新方法多得多,但这也许只是因为 Fortran 90 的使用仍然多于 Fortran 2003。
作为快速计时检查,我在 gfortran 4.8.5 下循环上述代码 100,000,000 次,发现较新的方式似乎也更快,运行时间约为 4 秒(新方式),而运行时间为 6 秒(旧方式)。相反,在下面的评论中,@roygvib 得到的结果与 gfortran 8.2 基本相反。
另外,请注意这里最近对该问题的讨论: Fortran 讨论组
我想知道在现代 Fortran 中是否可以使用其本身或其中的一部分来分配可分配数组来执行此操作。这是一个简单的例子:
module modu
implicit none
type :: t
integer :: i
end type
contains
subroutine assign(a,b)
type(t), allocatable, intent(out) :: a(:)
type(t), intent(in) :: b
allocate(a(1))
a(1) = b
end subroutine
end module
!----------------------
program test
use modu
implicit none
type(t), allocatable :: a(:)
allocate(a(1))
a(1)%i = 2
call assign(a, a(1))
print*, a(1)%i
end program
Run Code Online (Sandbox Code Playgroud)
此代码使用 ifort 18 给出正确的答案,并使用 gfortran 7.4 返回“分段错误”。
注意:原来的问题有点复杂,因为call assign(a, a(1))应该call assign(a, a(1)+b)用运算符 + 正确重载来替换,但结论(尊重 ifort 和 gfortran)是相同的。