fortran中逻辑数据类型,在内存中的存储情况?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fortran中逻辑数据类型,在内存中的存储情况?相关的知识,希望对你有一定的参考价值。

我们知道C中没有逻辑类型的,非0即真。
可是在Fortran中存在logical类型,有两种值,真(.true.)/假(.false.)。
在进行如下计算:
write(*,*) .true.+0
write(*,*) .ture.+1
write(*,*) .false.+0
write(*,*) .false.+1

输出结果如下:

是否可以说明,true在某种以上,true和-1,false和0,是有联系的。
我觉得这问题基本可以从true 和false在内存中的情况,可以解释清楚。
但是如何才能了解内存情况呢?这就是我标题中的问题。

你的分析对于你正在用的编译器看上去是正确的。不一定适合别的编译器。
因为 Fortran 标准没有规定逻辑值 统一的内存表示方法。

下面是 GNU fortran 的说明。

5.2 Internal representation of LOGICAL variables
The Fortran standard does not specify how variables of LOGICAL type are represented,
beyond requiring that LOGICAL variables of default kind have the same storage size
as default INTEGER and REAL variables. (这段说,Fortran 标准没有规定逻辑值统一的内存表示方法,默认逻辑值占内存大小与INTEGER and REAL 相同)

The GNU Fortran internal representation is as follows.
A LOGICAL(KIND=N) variable is represented as an INTEGER(KIND=N) variable, however, with only two permissible values: 1 for .TRUE. and 0 for .FALSE.. Any other integer value results in undefined behavior. (这段说 GNU Fortran 逻辑值 用整型表示时,1为.TRUE. ,0 为 .FALSE。其它无定义,导致“undefined behavior“)

Note that for mixed-language programming using the ISO_C_BINDING feature, there is a C_BOOL kind that can be used to create LOGICAL(KIND=C_BOOL) variables which are interoperable with the C99 _Bool type.
The C99 _Bool type has an internal representation described in the C99 standard, which is identical to the above description, i.e. with 1 for true and 0 for false being the only permissible values. Thus the internal representation of LOGICAL variables in GNU Fortran is identical to C99 _Bool, except for a possible difference in storage size depending on the kind
(这段谈,Fortran 与 C 语言混合 程序里的处理方法).
参考技术A logical型占有4字节,32位。但实际上,真和假只要1位就可以了。

如何用32位表达真和假两个状态呢?这个不同的语言有不同的规定。
在C语言里:00000000代表假,00000001代表真。也就是0和1。
而 Fortran 不同,它的 00000000代表假,FFFFFFFF代表真。

而FFFFFFFF如果表示整型,正好是 -1。因此就出现了你那种计算结果。追问

在C语言里:00000000代表假,00000001代表真。也就是0和1。
C中非0及真,所以1只是特例。

参考技术B 与逻辑变量长度有关,以Logical(4)为例,在内存中的实际存贮内容是:
FFFFFFFF=.T. --->对应整形数-1
00000000=.F. -->对应整形数0

确定内存中的 Fortran 派生类型大小

【中文标题】确定内存中的 Fortran 派生类型大小【英文标题】:Determine Fortran derived type size in memory 【发布时间】:2014-04-16 10:10:28 【问题描述】:

Fortran 内部函数transfer 可用于将派生类型转换为实数或整数数组。在依赖原始类型(整数、实数等)数组进行持久性的遗留系统中工作时,这可能非常有用。

下面的代码至少在ifortgfortran 上运行,并将简单的派生类型示例转换为整数数组(已更新解决方案):

program main
    implicit none

    integer, parameter :: int_mem_size = storage_size(1)

    type subtype
       integer a
       double precision b
    end type subtype

    type :: mytype
         integer :: foo
         double precision :: bar
         type(subtype) :: some_type
    end type

    type(mytype)  :: my_var
    type(subtype) :: my_subtype

    ! Old version: integer :: x(30)
    integer, allocatable :: x(:)
    integer :: mem_size

    !Allocate array with required size
    mem_size = storage_size(my_var)
    allocate(x(mem_size/int_mem_size))

    my_subtype%a = 1
    my_subtype%b = 2.7

    my_var%foo = 42
    my_var%bar = 3.14
    my_var%some_type = my_subtype

    write(*,*) "transfering..."
    x = transfer(my_var, x)
    write(*,*) "Integer transformation:", x

end program main

在我的电脑上,这是输出(这个结果至少取决于平台):

 transfering...
 Integer transformation:                    42           0  1610612736  1074339512         
 999           0    -1610612736  1074108825

我的问题是我已经“猜到”了一个 30 元素长的整数数组足够大来存储这个数据结构。有没有办法确定数组需要多大才能存储整个数据结构?

【问题讨论】:

【参考方案1】:

如果您有一个兼容 Fortran 2008 的编译器,或者一个足够兼容的编译器,您会发现内部函数 storage_size 返回用于存储其参数的位数。我熟悉的大多数编译器都没有实现非标准函数来执行此操作;英特尔 Fortran 编译器有一个名为 sizeof 的函数,它返回存储其参数所需的字节数。

【讨论】:

这似乎可以解决问题,谢谢!我已经更新了示例代码,以向任何感兴趣的人反映此解决方案

以上是关于fortran中逻辑数据类型,在内存中的存储情况?的主要内容,如果未能解决你的问题,请参考以下文章

派生数据类型中的 Fortran、参数和静态表

对象在类中的存储方式有哪些?

在默认类型和 C 互操作类型之间转换 Fortran 字符和逻辑数组

在默认类型和 C 互操作类型之间转换 Fortran 字符和逻辑数组

使用 Fortran 中的内存数据调用 C 代码

Fortran:普通数组与存储相同数据量的对象所需的 RAM