将 Fortran 数组重新解释为字节
Reinterpret a Fortran array as bytes
我想将 Fortran(real*8
,比方说)数组解释为字节数组,以便可以将其发送到函数以在字节级别上处理事物。实现此目的的简单(最好是无复制)方法是什么?
首先,不清楚什么是字节级别的函数。它使用 Fortran 字符吗?还是 1 字节整数?它们在 Fortran 中是不同的野兽。
您可以尝试对函数的签名撒谎,然后按原样传递数组。可能工作,不严格符合标准。
Transfer()
是用于类似目的的最佳现代工具,但它确实可能涉及临时对象。
如果数组的大小是固定的(它不是可分配的或指针或伪参数),您可以使用 equivalence
,这与 C 中的 union
非常相似。
但是你必须小心什么是允许的,这是一个出了名的危险区域。甚至 C 联合规则也不同于 C++ 规则。恐怕 Fortran 等价有自己的规则,而且更严格。类型双关是不允许的,但很多代码都是这样做的。
使用 C 指针进行技巧操作并从具有不同类型的不同指针指向同一个数组绝对不符合标准,并且在某些情况下可能会给出预期的结果,而在其他情况下可能会给出错误的结果(在 C 中称为未定义行为和 C++)。
"NO_COPY" 方式...但依赖于 DEC 扩展:
USE ISO_C_BINDING
IMPLICIT NONE
UNION
MAP
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
END MAP
MAP
BTYE , DIMENSION(N*8) :: B_Data
END MAP
MAP
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
END MAP
MAP
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
END MAP
MAP
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
END MAP
END UNION
如果无法访问 DEC 扩展,@Valdimir 等效项也有效。
计划对 gfortran 进行升级以添加 MAP 和 UNION DEC 扩展,因此及时也会有。
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56226
我对差异的欣赏又回到了正轨...
可以在结构内部使用 UNION/MAP。在 structure/TYPE 之外,EQUIVALENCE 可以满足所有需要。
正如 Vladimir 提到的,这也是一个 "no copy"...
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
BTYE , DIMENSION(N*8) :: B_Data
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
EQUIVALENCE(R8_Data, I4_Data)
它几乎比它的价值更危险,除非有特定的问题。
我想将 Fortran(real*8
,比方说)数组解释为字节数组,以便可以将其发送到函数以在字节级别上处理事物。实现此目的的简单(最好是无复制)方法是什么?
首先,不清楚什么是字节级别的函数。它使用 Fortran 字符吗?还是 1 字节整数?它们在 Fortran 中是不同的野兽。
您可以尝试对函数的签名撒谎,然后按原样传递数组。可能工作,不严格符合标准。
Transfer()
是用于类似目的的最佳现代工具,但它确实可能涉及临时对象。
如果数组的大小是固定的(它不是可分配的或指针或伪参数),您可以使用 equivalence
,这与 C 中的 union
非常相似。
但是你必须小心什么是允许的,这是一个出了名的危险区域。甚至 C 联合规则也不同于 C++ 规则。恐怕 Fortran 等价有自己的规则,而且更严格。类型双关是不允许的,但很多代码都是这样做的。
使用 C 指针进行技巧操作并从具有不同类型的不同指针指向同一个数组绝对不符合标准,并且在某些情况下可能会给出预期的结果,而在其他情况下可能会给出错误的结果(在 C 中称为未定义行为和 C++)。
"NO_COPY" 方式...但依赖于 DEC 扩展:
USE ISO_C_BINDING
IMPLICIT NONE
UNION
MAP
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
END MAP
MAP
BTYE , DIMENSION(N*8) :: B_Data
END MAP
MAP
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
END MAP
MAP
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
END MAP
MAP
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
END MAP
END UNION
如果无法访问 DEC 扩展,@Valdimir 等效项也有效。
计划对 gfortran 进行升级以添加 MAP 和 UNION DEC 扩展,因此及时也会有。
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56226
我对差异的欣赏又回到了正轨... 可以在结构内部使用 UNION/MAP。在 structure/TYPE 之外,EQUIVALENCE 可以满足所有需要。
正如 Vladimir 提到的,这也是一个 "no copy"...
REAL(KIND=C_DOUBLE) , DIMENSION(N) :: R8_Data
BTYE , DIMENSION(N*8) :: B_Data
CHARACTER(LEN=1) , DIMENSION(N*8) :: C_Data
INTEGER(KIND=C_Int16_T), DIMENSION(N*4) :: I2_Data
INTEGER(KIND=C_Int32_T), DIMENSION(N*2) :: I4_Data
EQUIVALENCE(R8_Data, I4_Data)
它几乎比它的价值更危险,除非有特定的问题。