我编写了以下函数来接受六个实值参数并返回一维数组。
FUNCTION G(a, b, c, d, e, f)
IMPLICIT NONE
! SPECIFICATION SECTION
REAL, INTENT(IN) :: a
REAL, INTENT(IN) :: b
REAL, INTENT(IN) :: c
REAL, INTENT(IN) :: d
REAL, INTENT(IN) :: e
REAL, INTENT(IN) :: f
REAL, DIMENSION(1:3) :: G
REAL, DIMENSION(3,3) :: T
REAL, DIMENSION(1:3) :: H
! EXECUTION SECTION
T = RESHAPE( (/1, 0, -sin(b), &
0, cos(a), sin(a)*cos(b), &
0, -sin(a), cos(a)*cos(b)/), &
(/3,3/) )
H = (/d, e, f/)
G = someOtherUnimportantFunction(H,T)
! SUBPROGRAM SECTION
END FUNCTION G
此函数无法编译并导致RESHAPE函数调用行的错误:
error #7113: Each ac-value expression in an array-constructor must have the same type and type parameters. [COS]
对于上述文本,总共有5个错误重复此错误,但最后4个错误在最后没有[COS]
。这个错误似乎表明1和0被解释为与trig函数不同的类型,实际上,如果我将1更改为1.0并将0更改为0.0,则函数可以正确编译。然而,这是令人困惑的,因为我有许多类似的函数,除了正弦和角度的余弦之外,还有类似的RESHAPE
调用,整数类型表达式为1和0。那些RESHAPE
函数调用编译得很好。为什么这个RESHAPE呼叫有什么不同?
据我所知,以前的RESHAPE
命令隐式地将整数转换为REAL值变量。为什么现在没有发生这种类型的转换呢?
使用混合整数和REAL数据类型正确编译RESHAPE调用的示例:
U = RESHAPE( (/cos(j), 0, sin(j), 0, 1, 0, -sin(j), 0, cos(j)/),(/3, 3/) )
U是REAL 3x3数组,j是REAL值角度。
答案 0 :(得分:1)
从某些实验来看,上面观察到的reshape
(或更确切地说,在reshape
函数内创建的临时数组)的行为似乎是某些特定版本编译器的供应商扩展(可能是ifort14) ?)。请比较下面B
和C
的结果,具体取决于所使用的编译器和版本。
! [compilers used]
! ifort 14 and 16 (both with an option '-standard-semantics')
! gfortran 4.8 and 7.1
! Oracle studio fortran 12.5
! PGI Fortran Community Edition 2017.4
program main
implicit none
real :: A( 3 ), B( 3 ), C( 3 )
!-------------------------
! RHS = uniform integer array
A = [ 1, 2, 3 ] !! an integer temporary array is created for RHS and assigned to A (with integer -> real conversion)
print *, [ 1, 2, 3 ]
print *, "A = ", A
! gfortran: PASS
! ifort16 : PASS
! ifort14 : PASS
! oracle : PASS
! pgi : PASS
!-------------------------
! RHS = [ real, integer, integer ]
B = [ 1.1, 2, 3 ]
print *, [ 1.1, 2, 3 ]
print *, "B = ", B
! gfortran: Error: Element in REAL(4) array constructor at (1) is INTEGER(4)
! ifort16 : Error: If type specification is omitted, each element
! in an array-constructor must have the same type
! and kind type parameters.
! ifort14 : PASS (*)
! oracle : Error: All ac-value expressions in an array constructor
! must have the same type and type parameters.
! pgi : PASS (*)
!-------------------------
! RHS = [ integer, real, integer ]
C = [ 1, 2.2, 3 ]
print *, [ 1, 2.2, 3 ]
print *, "C = ", C
! gfortran: Error: Element in INTEGER(4) array constructor at (1) is REAL(4)
! ifort16 : Error: (same message as for B)
! ifort14 : Error: Each ac-value expression in an array-constructor
! must have the same type and type parameters.
! oracle : Error: (same message as for B)
! pgi : PASS (**)
! The error message from ifort-14 is the same as that shown in the question.
end
结果:
!-------------------------
gfortran, ifort-16, oracle
1 2 3
A = 1.000000 2.000000 3.000000
! B and C => error
!-------------------------
ifort-14
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000 (*)
B = 1.100000 2.000000 3.000000 (*)
! C => error
!-------------------------
PGI
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1 2 3 (**)
C = 1.000000 2.000000 3.000000 (**)
因此,在数组构造函数中混合使用不同类型的元素可能更具可移植性(即使某些编译器允许它...)。
另一方面,如果我们将数组构造函数的(统一)元素类型指定为[ real :: ... ]
(如注释中所示),我们可以混合使用不同类型的元素,例如:
B = [ real :: 1.1, 2, 3 ]
print *, [ real :: 1.1, 2, 3 ]
print *, "B = ", B
C = [ real :: 1, 2.2, 3 ]
print *, [ real :: 1, 2.2, 3 ]
print *, "C = ", C
给出(对于上面的所有编译器):
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1.000000 2.200000 3.000000
C = 1.000000 2.200000 3.000000
(*)由于integer
被转换为real
,因此这种模式似乎只是允许而且几乎没有什么危害。
(**)但我认为这种模式可能存在问题(取决于案例),因为real
是隐含的"向下转换"到integer
(这可能不是程序员的意图......)