编辑:Gfortran 6现在支持这些扩展:)
我有一些旧的f77代码,广泛使用UNION和MAP。我需要使用gfortran编译它,它不支持这些扩展。我已经想出如何转换所有不支持的扩展,除了这些,我不知所措。我对可能的方法有几点想法,但未能成功实现任何方法。我需要以与它们当前相同的方式访问现有的UDT;我可以重新实现UDT,但它们的接口不能改变。
我的例子:
TYPE TEST
UNION
MAP
INTEGER*4 test1
INTEGER*4 test2
END MAP
MAP
INTEGER*8 test3
END MAP
END UNION
END TYPE
必须以下列方式访问元素:TEST%test1,TEST%test2,TEST%test3
我的想法如此:
我想当UNION和MAP被排除在标准之外时,必须对f77到f90 / 95进行大量重构。如果处理这个怎么办?
编辑:接受的答案有一个允许内存重叠的解决方法,但就保留API而言,这是不可能的。
答案 0 :(得分:3)
UNION和MAP从未成为任何FORTRAN标准的一部分,它们是供应商扩展。 (参见,例如,http://fortranwiki.org/fortran/show/Modernizing+Old+Fortran)。因此他们并没有真正被排除在Fortran 90/95标准之外。它们导致变量在内存中重叠。如果代码实际使用此功能,则您需要使用equivalence
。在不进行转换的情况下在不同类型的变量之间移动数据的首选方法是transfer
内在的,但是您必须确定需要进行转换的每个位置,而equivalence
正在进行转换。含蓄。当然,这使得代码不易理解。如果内存叠加只是为了节省空间并且没有使用变量的等价,那么你可以摆脱这个“特性”。如果代码就像你的例子,用小整数,那么我猜测正在使用内存叠加。如果叠加层是大型阵列,则可能已经完成以节省内存。如果这些声明也在创建新类型,则可以使用用户定义的类型,这些类型绝对是Fortran> = 90的一部分。
如果代码使用不同类型的变量的内存等价,则这可能不是可移植的,例如,整数和最终运行的机器与当前机器之间的整数和实数的内部表示可能不同。或许这些变量只是用来存储比特。有很多要弄清楚。
P.S。在回答评论中的问题时,这是一个代码示例。但是......要明确......我不认为使用等价是良好的编码实践。使用gfortran通常用于调试代码的编译器选项,gfortran拒绝此代码。有了更宽松的选项,gfortran将编译它。 ifort也是如此。
module my_types
use ISO_FORTRAN_ENV
type test_p1_type
sequence
integer (int32) :: int1
integer (int32) :: int2
end type test_p1_type
type test_p2_type
sequence
integer (int64) :: int3
end type test_p2_type
end module my_types
program test
use my_types
type (test_p1_type) :: test_p1
type (test_p2_type) :: test_p2
equivalence (test_p1, test_p2)
test_p1 % int1 = 2
test_p1 % int1 = 4
write (*, *) test_p1 % int1, test_p1 % int2, test_p2 % int3
end program test
答案 1 :(得分:1)
问题在于联盟是用于节省空间还是用于替代相同数据的表示。如果要移植,请查看它的使用方法。也许,因为空间有限,它的编写方式必须共享变量。如今拥有更大的内存量,这可能不是必需的,并且可能不需要联合。在这种情况下,它只是两种不同的类型
答案 2 :(得分:1)
对于那些只想用这些扩展编译代码的人:Gfortran现在支持版本6中的UNION,MAP和STRUCTURE。https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56226