现代 Fortran 中的整数精度

Integer precision in modern Fortran

selected_int_kind(int16) 的值显示为 1 而不是 2。这是编译器错误吗?

在以下输出中,请注意 bint 的差异,本意为 2 个字节,INT16。 (为清楚起见,添加了注释 <===。)

compiler version  = GCC version 5.1.0
compiler options  = -fPIC -mmacosx-version-min=10.9.4 -mtune=core2 -Og -Wall -Wextra -Wconversion -Wpedantic -fcheck=bounds -fmax-errors=5
execution command = ./a.out

Number of bytes in type default = 4
Number of bytes in type int_8 = 1
Number of bytes in type int_16 = 2         <===
Number of bytes in type int_32 = 4
Number of bytes in type int_64 = 8
Number of bytes in type int_a = 1
Number of bytes in type int_b = 1          <===
Number of bytes in type int_c = 2
Number of bytes in type int_d = 4
Value of aint = 1
Value of bint = 1                          <===
Value of cint = 2
Value of dint = 4
Value of selected_int_kind ( INT16 ) = 1   <===

以下代码供读者研究此问题。有问题的作业在第 13 行。

program bytes
    use iso_fortran_env
    implicit NONE

    integer           :: default

    integer ( int8  ) :: int_8
    integer ( int16 ) :: int_16
    integer ( int32 ) :: int_32
    integer ( int64 ) :: int_64

    integer, parameter :: aint = selected_int_kind ( INT8 )
    integer, parameter :: bint = selected_int_kind ( INT16 )
    integer, parameter :: cint = selected_int_kind ( INT32 )
    integer, parameter :: dint = selected_int_kind ( INT64 )

    integer ( aint ) :: int_a
    integer ( bint ) :: int_b
    integer ( cint ) :: int_c
    integer ( dint ) :: int_d

    character ( len = * ), parameter :: c_options = compiler_options( )
    character ( len = * ), parameter :: c_version = compiler_version( )
    character ( len = 255 )          :: cmd = " "

        call get_command ( cmd )

        write ( *, '(    "compiler version  = ", g0    )' ) c_version
        write ( *, '(    "compiler options  = ", g0    )' ) trim ( c_options )
        write ( *, '(    "execution command = ", g0, / )' ) trim ( cmd )

        write ( * , 100 ) 'default', sizeof ( default )

        write ( * , 100 ) 'int_8', sizeof ( int_8 )
        write ( * , 100 ) 'int_16', sizeof ( int_16 )
        write ( * , 100 ) 'int_32', sizeof ( int_32 )
        write ( * , 100 ) 'int_64', sizeof ( int_64 )

        write ( * , 100 ) 'int_a', sizeof ( int_a )
        write ( * , 100 ) 'int_b', sizeof ( int_b )
        write ( * , 100 ) 'int_c', sizeof ( int_c )
        write ( * , 100 ) 'int_d', sizeof ( int_d )

        write ( * , 110 ) 'aint', aint
        write ( * , 110 ) 'bint', bint
        write ( * , 110 ) 'cint', cint
        write ( * , 110 ) 'dint', dint

        write ( * , 110 ) 'selected_int_kind ( INT16 )', selected_int_kind ( INT16 )

  100   format ( "Number of bytes in type ", g0, " = ", g0 )
  110   format ( "Value of ", g0, " = ", g0 )

end program bytes

这不是错误。标准(Fortran 95 13.14.94、Fortran 2003 13.7.105 和 Fortran 2008 13.7.146)对 selected_int_kind(R) 有这样的说法:

Argument. R shall be an integer scalar.

Result Value. The result has a value equal to the value of the kind type parameter of an integer type that represents all values n in the range −10R < n < 10R, or if no such kind type parameter is available on the processor, the result is −1. If more than one kind type parameter meets the criterion, the value returned is the one with the smallest decimal exponent range, unless there are several such values, in which case the smallest of these kind values is returned.

这意味着,如果 int16 在您的平台上恰好是 2,则 selected_int_kind(2) 将 return 能够表示范围的最小整数类型 - 100到+100,是一个存储大小为1的单字节,所以int8的值为returned.

下面一个简单程序的输出应该演示它是如何工作的:

 Value of int8            1
 Value of int16           2
 Value of int32           4
 Value of int64           8
 Value of selected_int_kind(1)            1
 Value of selected_int_kind(2)            1
 Value of selected_int_kind(3)            2
 Value of selected_int_kind(4)            2
 Value of selected_int_kind(5)            4
 Value of selected_int_kind(6)            4
 Value of selected_int_kind(7)            4
 Value of selected_int_kind(8)            4
 Value of selected_int_kind(9)            4
 Value of selected_int_kind(10)            8
 Value of selected_int_kind(11)            8
 Value of selected_int_kind(12)            8
 Value of selected_int_kind(13)            8
 Value of selected_int_kind(14)            8
 Value of selected_int_kind(15)            8
 Value of selected_int_kind(16)            8
 Value of selected_int_kind(17)            8
 Value of selected_int_kind(18)            8
 Value of selected_int_kind(19)           16
 Value of selected_int_kind(20)           16
 Value of selected_int_kind(21)           16
 Value of selected_int_kind(22)           16

This file was compiled by GCC version 5.2.0 using the options -mtune=generic -march=x86-64 -std=f2008