Fortran 中不同类型整数之间的转换规则是什么?

What are the rules surrounding conversion between different kinds of integers in Fortran?

考虑以下代码片段:

    integer(int8) :: a
    integer(int32) :: b
    integer(int64) :: c
    a = - huge(a) - 1
    b = - huge(b) - 1
    c = - huge(c) - 1
    print *, a, b, c
    a = int(b, kind=int8)
    c = int(b, kind=int64)
    print *, a, b, c

在我的系统上它给出了以下输出:

 -128 -2147483648 -9223372036854775808
    0 -2147483648          -2147483648

这表明不同种类整数之间的转换发生如下:

  1. 扩大整数转换[更少的字节到更多的字节]是通过符号扩展完成的。
  2. 缩小整数转换[更多字节到更少字节]是通过简单地去掉高阶位来完成的。

这类似于Java的整数转换规则。

行为是否定义为标准 Fortran?有什么方法可以覆盖规则 1 并简单地获得正常的加宽 [比如 Java 的 Integer.toUnsignedLong()]?

编译器信息:

GNU Fortran (Rev6, Built by MSYS2 project) 11.2.0
Copyright (C) 2021 Free Software Foundation, Inc.

在F2018的10.2.1.3(8)你会发现内在赋值右边表达式的值是按照一个table转换的。当分配给整数的变量时,INT() 内部函数与变量的种类一起使用。

INT() 内部函数的定义是 (16.9.100(5)):

Result Value.
Case (i): If A is of type integer, INT (A) = A.
...

其中 A 是参数。

所以它只是说值被复制了。如果该值不合适,那你就不走运了。 Fortran 标准没有定义会发生什么,因为(正如@steve 所指出的):

F2018 16.9.1(2)

A program shall not invoke an intrinsic procedure under circumstances where a value to be assigned to a subroutine argument or returned as a function result is not representable by objects of the specified type and type parameters.

这使您的程序不符合规范。在 C 中,他们会说行为是未定义的(不仅仅是实现定义的)。


如果启用 -Wconversion 并在没有显式 int() 内在的情况下进行赋值,您将收到可能值更改的警告。确实,在a = b你可以看到这样的变化。

如果启用 -fsanitization=undefined 并执行相同的操作,则可能会出现运行时错误。我现在重现不了,但我以前确实打过这样的东西。

触发检查必须是真正的运行时:

    use iso_fortran_env
    integer(int32) :: b
    read *,b
    b = 2*b
    print *, b
end


> gfortran conversion2.f90 -fsanitize=signed-integer-overflow
> ./a.out 
2000000000
conversion2.f90:4: runtime error: signed integer overflow: 2000000000 * 2 cannot be represented in type 'integer(kind=4)'
  -294967296