在C ++中这是被接受的:
uint64_t mask = 0x7FC0000FF80001FFLL;
但是在fortran中
integer(kind=8), parameter :: mask = Z'7FC0000FF80001FF'
不适用于gfortan。 我认为它们都是64位值?不是吗?
gfortran抱怨道:
从INTEGER(16)转换为INTEGER(8)
的算术溢出
编辑:
所以,抱歉混淆,这里有一些更加扩展的问题描述。 我将在Fortran中进行一些转换,并在c ++中提供一些示例代码。 在示例c ++代码中,掩码定义如下:
typedef uint64_t mask;
static const mask dilate_2 = (mask)0x7FC0000FF80001FFLL ;
static const mask dilate_1 = (mask)0x01C0E070381C0E07LL ;
static const mask dilate_0 = (mask)0x9249249249249249LL ;
从我糟糕的c ++理解,我认为十六进制值是64位 整数值(它们在结尾处有LL)。 现在在Fortran我的问题首先是,用
定义integer(kind=8), parameter ...
弗拉基米尔说,没有用,因为
integer(kind=8), ...
可能不是64位整数
比我测试的Alexanders解决方案,适用于第一个和第一个
第二(dilate_2,dilate_1)常数
弗拉基米尔解决方案也适用于这两个。
现在对于dilate_0,这些解决方案都不起作用。我认为弗拉基米尔解决方案将投射0x9249249249249249LL(实际上是什么
比INT64中允许的更大的整数到INT64中
如果我这样做:
integer(INT64), parameter :: dilate_0 = int(Z'9249249249249249', &
kind=kind(dilate_0)
但这也不起作用,gfortran给我一个错误:
错误:算术溢出在(1)处将INTEGER(16)转换为INTEGER(8)。
所以我的实际问题是如何在Fortran中实现这个常量?
答案 0 :(得分:3)
正如弗拉基米尔在他的评论integer(kind=8)
中发表的那样不可移植(而不是编译器抱怨的那种16
)。
作为补救措施,我建议使用内部模块ISO_Fortran_env
(Fortran 2003),它对于所使用的编译器有很多predefined constants。使用此模块中的INT64
可以解决您的问题并生成可移植代码:
program test
use,intrinsic :: ISO_Fortran_env, only: INT64
integer(INT64), parameter :: mask = Z'7FC0000FF80001FF'
print *,mask
end program
答案 1 :(得分:1)
Z'9249249249249249'
无法表示为INT64(相当于gfortran中的INTEGER(kind=8)
)因为
INTEGER(KIND=16)
。
然后我们有参数staement,其中INTEGER(KIND=8)
参数应该被赋予超出其范围的值。这就是编译器抱怨的内容。它会以同样的方式抱怨
INTEGER(KIND=4), PARAMETER :: N = 37094947285
如果你想解决这个问题,你可以使用-fno-range-check选项来gfortran。有关-fno-range-check
的信息已包含在gfortran错误消息中(您未显示的部分)。
答案 2 :(得分:0)
我会这样做以保持标准符合
integer(whatever), parameter :: mask = int(Z'7FC0000FF80001FF', &
kind=kind(mask))
其中whatever
是所需值的某种常量。它可能是int64
。
如果常数对应于负数,则上述操作无效。然后必须制作一个技巧:
integer(int32), parameter :: mask = transfer(int(Z'A0000000',int64),1_int32)
或
integer(int32), parameter :: mask = transfer(Z'A0000000',1_int32)
但我不确定最后一个是否严格符合标准。