【发布时间】:2018-12-21 18:01:38
【问题描述】:
我有以下 Fortran 函数 create_pointer 调用名为 create_pointer 的 C 函数,该函数创建一个指针并返回其地址:
FUNCTION create_pointer() RESULT(c_intptr_t) BIND(C, name = "create_pointer")
USE, INTRINSIC :: iso_c_binding, ONLY: c_intptr_t
END FUNCTION
作为参考,C 函数create_pointer 如下:
intptr_t create_pointer(void)
{
void *ptr;
intptr_t address;
ptr = malloc(100);
address = (intptr_t) ptr;
printf("FROM C: address %p\n", address)
return address;
}
现在,当编译(使用 GCC 4.9)并在 Mac OS X 64 位中执行以下 Fortran 程序时:
PROGRAM
INTEGER(c_intptr_t) :: address
address = create_pointer()
WRITE(*, '(Z8)') "FROM FORTRAN:", address
END PROGRAM
它给出了一个可能与此类似的意外输出:
FROM C: address 0x7f8870c3ee00
FROM FORTRAN: address 70C3EE00
为什么在 C 中显示的地址与在 Fortran 中显示的地址不同?我会假设 ISO_C_binding c_intptr_t 将保留这两种语言之间的正确值。此外,可以注意到,Fortran 从 C 接收的地址包含在其中(换句话说,初始值 0x7f88 被丢弃)。是不是因为 64 位地址计数中只有前 48 位,而 ISO_C_binding 丢弃了后 16 位?
仅供参考,这次在 Ubuntu 64 位编译(使用 GCC 4.9)并运行相同的 Fortran 程序时,输出是一致的(即 C 和 Fortran 显示的地址相同)。
【问题讨论】:
-
在 Mac 上,您确定您使用的是实际的 GCC 而不是 Clang(因为默认情况下链接到
gcc和g++命令)? -
是的,它是 GCC。运行
gfortran -v和gcc -v时,它们都返回gcc version 4.9.4 (MacPorts gcc49 4.9.4_3)。 -
70c3ee00是地址的低 32 位。这表明c_intptr_t被错误地定义为 32 位而不是 64 位的数量。我不知道你如何在 Fortran 中声明一个 64 位整数,但如果你将address的 Fortran 端声明和create_pointer上的 RESULT 声明更改为任何内容,你现在得到正确的值了吗? -
@zwol,通常
c_intptr_t如果编译为 32 位,则自动具有 4 个字节的大小,如果编译为 64 位,则自动具有 8 个字节的大小,所以我认为问题不存在。尽管如此,我尝试过使用c_int64_t和c_long_long,但它们都没有工作(即它们显示与c_intptr_t相同)。 -
但现在我发现了问题:请将
implicit none添加到您的 Fortran 程序中。你的函数create_pointer被假定返回一个默认的真实结果,因为你实际上并没有包含你在主程序中给出的接口。