You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran内存地址输出差异问题:为何loc结果有时有效有时为0

Fortran数组参数的loc输出差异与指针访问问题

代码与运行结果

$ cat whereis.F90
program whereisit

integer, target :: a(100)
integer, pointer :: b(:)

print '("a is at 0x",Z8)', loc(a)
call just_checking_1(a)
call just_checking_2(a)

b => a
print '("b is at 0x",Z8)', loc(b)
call just_checking_p(b)

end program



subroutine just_checking_1(a)
integer :: a(*)     !<-- 注意: a(*)
print '("In just_checking_1 a is at 0x",Z8)', loc(a)
end subroutine


subroutine just_checking_2(a)
integer :: a(:)    !<-- 注意: a(:)
print '("In just_checking_2 a is at 0x",Z8)', loc(a)
end subroutine


subroutine just_checking_p(b)
integer, pointer, intent(in) :: b(:)
print '("In just checking b is at 0x",Z8)', loc(b)
end subroutine

运行输出:

$ ./a.out
a is at 0x  6B4140
In just_checking_1 a is at 0x  6B4140
In just_checking_2 a is at 0x       0
b is at 0x  6B4140
In just checking b is at 0x       0

为什么just_checking_1和just_checking_2的输出不一样?

你的推测完全正确,核心就是假定大小数组(a(*))和假定形状数组(a(:))的底层传递机制不同:

  • 假定大小数组a(*):
    这是Fortran传统的数组传递方式,编译器直接把原数组的起始内存地址传给子程序。所以loc(a)返回的就是主程序中数组a的实际起始地址,两者输出一致。它不携带数组的形状信息,需要额外手段(比如另一个参数)来确定数组大小。

  • 假定形状数组a(:):
    这种参数传递的是一个数组描述符,而非数组数据本身。描述符里存着数组的起始地址、维度、步长等元数据。此时loc(a)取的是这个描述符的内存地址,而非数组数据的地址。有些编译器会把描述符放在临时内存区域,甚至返回0(因为loc函数对描述符的行为没有标准化定义),这就是你看到输出0的原因。

简单总结:a(*)传的是数据地址,a(:)传的是管理数组的“元数据容器”地址,loc对两者的作用对象完全不同。


just_checking_p能访问指针b指向的内存吗?

完全可以,loc(b)输出0不代表指针无法访问目标内存:

  • 子程序中的指针形参b(:)传递的也是描述符,loc(b)取的是这个描述符的地址,不是指针指向的数据地址。但描述符里已经包含了指针目标的内存地址、形状等关键信息。
  • 在子程序中,你可以正常使用b来读写它指向的内存(比如执行print *, b(1)或者b(5)=99),不会有任何问题。
  • 主程序中loc(b)返回的是指针指向的数据地址,这是因为主程序里b是指针变量,loc作用于它时,语义是返回指针的目标地址;而子程序里b是指针形参,loc的作用对象变成了形参的描述符,两者语义不同而已。

内容的提问来源于stack exchange,提问作者bob.sacamento

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 03:53:10