我有一个C库,它在结构中声明了几个long
变量。在Fortran中,我通常将它们视为integer(kind=c_long)
,但这在特定的更复杂的程序中会导致意想不到的问题。我的Fortran代码在32位系统中可以正常运行,在64位系统中甚至无法编译。原因太复杂了,无法在这里解释,对于问题的目的来说,这并不重要,但归根结底,c_long
在32位和64位系统中是不一样的。至少在gfortran中,c_long
在32位中是4字节,在64位中是8字节。事实上,c_long = c_int = 4
是32位的,而c_long = c_double = 8
是64位的。
现在,在这个特定的C库中,long
整数只用于char
变量,使用的最大值是$FFFFFF,远远超出了32位系统中c_long
整数的限制,因为huge(1_c_long)=$7FFFFFFF
是32位系统。所以我有几种方法来摆脱这个问题,但我仍然想知道……为什么要以这种方式出现呢?例如,c_double
在32位和64位系统中都是相同的(应该如此);同样的c_int
,它是相同的,无论什么。为什么c_long
是不同的?我花了好几个小时才弄清楚一个复杂的程序是怎么回事。
long
(甚至int
)没有统一的长度。各种系统和编译器使用一种通用的数据模型(维基百科),int
,long
,long long
和指针使用32位或64位。
Fortran使用伴随处理器的概念指定iso_c_binding
类型。. 这意味着Fortran编译器在其特定配置(在特定操作系统中)中使用这些类型来与特定操作系统中具有某些特定配置的特定C编译器兼容。
值得注意的是,Microsoft Windows上的Microsoft和MinGW C编译器使用LLP64模型。Linux和其他unix上的编译器通常使用LP64数据模型。因此,long
的大小不同。
如果没有具体的细节(编译器,操作系统),很难对您的情况说更多。但是这些大小不是通用的,只对特定操作系统上的特定编译器有效,Fortran编译器将其视为配套处理器。
下面的小程序揭示了正在发生的事情:
#include <limits.h>
#include <stdio.h>
int main() {
printf(" Maximum int: %X (%u bytes)n",INT_MAX,sizeof(int));
printf("Maximum long: %lX (%u bytes)n",LONG_MAX,sizeof(long));
return 0;
}
在32位GNU/Linux系统上使用gcc 11.2,得到:
Maximum int: 7FFFFFFF (4 bytes)
Maximum long: 7FFFFFFF (4 bytes)
在64位系统上,它给出:
Maximum int: 7FFFFFFF (4 bytes)
Maximum long: 7FFFFFFFFFFFFFFF (8 bytes)
因此,Fortran没有做错任何事。问题(或者不管你怎么称呼它)来自C端。没有标准——或者至少没有一个标准——并且C没有类似于Fortran的固定大小类型的东西(这不是完美的,但至少使事情不那么令人困惑)。long
整数在C中是不同的,这取决于您的操作系统。所以iso_c_binding
别无选择,只能提供不同的c_long
类型。
经验教训:永远不要假设任何事情。不存在一个单一的、通用的c_long
,正如Vladimir F指出的那样,也不存在一个单一的、通用的c_int
(或其他任何东西)。