【问题标题】:accessing unsigned integer values in fortran在 fortran 中访问无符号整数值
【发布时间】:2012-11-16 10:31:02
【问题描述】:

如果我在 Fortran 中有一个 c_int8_t 变量,并且想将底层位解释为无符号整数(用于索引而不是任何算术),那么进行转换的最有效方法是什么?我想做类似的事情

X( some_function( my_c_int8_t_var ) ) = 1

其中 X 是一个数组,some_function 应该返回一个包含 my_c_int8_t_var 的无符号值的 c_int16_t。我已经看到了包括 transfer、iadd 在内的选项(或者我猜只是一个带有强制转换和加法的简单条件),但我想知道最有效的方法是什么(这个索引是在内部循环中进行的)。当然,它不必是一个函数——如果它可以用一个内联表达式来完成,那就太好了。

编辑:如果该方法也适用于其他整数大小,那就太好了......即用于在 c_int32_t 中获取无符号 c_int16_t 的内容并将无符号 c_int32_t 获取到 c_int64_t 中。

【问题讨论】:

  • 不可能使用有符号整数的整个范围声明X,例如integer, dimension(-huge(my_c_int8_t_var) : huge(my_c_int8_t_var)) :: X?这样麻烦会少得多。
  • 我明白你的意思,但在我的情况下,我没有使用完整范围 - 用户传递最大值,我相应地分配 X 数组(X(Xm)此刻或 X(0 :(Xm-1)). 我希望能够支持全部范围的无符号整数(因此可以达到 256 个而不需要转到 2 字节数据) - 但永远不要为提供的最大值分配超过必要的值.
  • 哦,我明白了;我误解了这个问题的意图。

标签: integer fortran fortran95 fortran2003


【解决方案1】:

您可以使用transfer()ichar() 函数。类似的东西

X(ichar(transfer(my_c_int8_t_var,"a")))) = 1

例如

 use iso_c_binding
 write (*,*) ichar(transfer(-1_c_int8_t,"a"))

 end

返回 255。

当您找不到对应的字符类型(例如 16 位)时,我会编写一个函数,将 huge(1._my_integer_kind) 添加到值中。

integer function indx(i)
  integer(c_int16_t),intent(in) :: i

  if (i<0) then
    indx = 2*(huge(i)+1) + i
  else
    indx = i
  end if
end function indx

  integer function indx2(i)
    integer(c_int8_t),intent(in) :: i

    indx2 = TRANSFER([i,0_c_int8_t],1_c_int16_t)
  end function indx2

最后一种情况仅适用于 little-endian 平台。

你可以为这个函数创建一个通用接口。

 write (*,*) indx(-2_c_int16_t)

给出 65534

【讨论】:

  • 谢谢,这正是我正在寻找的技巧。但它似乎特定于 8 位案例。我知道这是我的例子,但我希望找到一些同样适用于将无符号 c_int16_t 值转换为 c_int32_t 等的方法。
  • 谢谢 - 巨大的方法 - 不需要有条件吗?对于无符号数据中的“正”值,我不想添加任何内容,只有在 i
  • 我想另一种方法是转移到更大的类型,然后使用适当的掩码进行按位与以将大位归零,但我不知道如何解决这个问题——也不确定如果这会比条件加法慢。
  • 但显然是 TRANSFER “如果结果的按位表示比 SOURCE 的长,则结果的前导位对应于 SOURCE 的前导位,并且任何尾随位被任意填充。”我不确定哪个前导和尾随是(就按位值的大小部分而言)......
  • 通过这些技巧,您必须了解 little-endian 和 big-endian 机器之间的差异以及由此导致的不可移植性。
【解决方案2】:

怎么样

integer(c_int16_t) :: i, i2(2)
integer(c_int32_t) :: i32

equivalence (i32, i2)

i2(2) = 0

然后在循环内

i2(1) = i
X(i32) = 1

这行得通吗?对于 little-endian 平台,我应该将 16 位数据放在 i2(1) 还是 i2(2) 中?

【讨论】:

  • 是的,但我会这样写,我会建议你 TRANSFER([i,0_c_int8_t],1_c_int16_t)
  • TRANSFER([i,(0_c_int16_t)],1_c_int32_t)
  • 啊,太好了...我不知道你可以在传输中混合数组和标量!
猜你喜欢
  • 1970-01-01
  • 2020-08-14
  • 2010-09-19
  • 2013-10-02
  • 1970-01-01
  • 2015-08-13
  • 2013-08-29
  • 2016-04-21
  • 2012-08-13
相关资源
最近更新 更多