【发布时间】:2014-09-21 08:24:08
【问题描述】:
我目前正在修复 C 代码中的遗留错误。在修复此错误的过程中,我将unsigned int 存储到unsigned long long 中。但令我惊讶的是,当我在 GCC 的 64 位版本上编译此代码时,数学停止工作。我发现问题在于,当我为 long long 分配一个 int 值时,我得到了一个看起来像 0x0000000012345678 的数字,但在 64 位机器上,这个数字变成了 0xFFFFFFFF12345678。
有人可以向我解释或指出某种规范或文档,说明在将较小的数据类型存储在较大的数据类型中时应该发生什么,以及在 C 中执行此操作的适当模式是什么?
更新 - 代码示例
这就是我正在做的事情:
// Results in 0xFFFFFFFFC0000000 in 64 bit gcc 4.1.2
// Results in 0x00000000C0000000 in 32 bit gcc 3.4.6
u_long foo = 3 * 1024 * 1024 * 1024;
【问题讨论】:
-
你如何存储值?如果你做了类似
int64_t my64bitInt = (int64_t)some32bitInt的事情,那么这不应该发生。您是在使用memcpy还是一些基于块的复制机制,还是像我上面的第一个示例那样进行直接分配?有一些方法可以通过使用基于块的复制而不是直接分配来实现这一点。在 C 中,向上转换是隐式的,并且保证无害,除非您在定点值和浮点值之间进行转换。 -
Unsigned long long 可以表示 unsigned int 的所有值,因此您描述的内容是不可能的。所以问题的关键部分是如何你做“分配”操作:)
-
添加了代码示例。该示例使用 int 常量,但如果 int 是变量,也会发生这种情况。
-
u_long foo = 3UL * 1024UL * 1024UL * 1024UL; -
为了便携,最好使用
unsigned long long而不是unsigned long。long在某些 64 位机器上只有 32 位长。该标准保证long long至少为 64 位。