如何在32位架构中分配64位无符号长long到32位结构

时间:2012-07-17 16:41:36

标签: c linux unix embedded 64-bit

我有2个内核,一个是32位,另一个是64位。

在64位机器上,我支持unsigned long long,我需要将这个值赋给一个可以在32位机器上访问的varriable,例如: -

typedef struct {
    unsigned int low;
    unsigned int high;
} myint64_t;

myint64_t app_sc;

以下是64位计算机的代码段:

unsigned long long sc;

/* Calculate sc */
...

现在在64位机器上,我需要分配" sc"到app_sc,并将其用于64位机器上的某些计算。

我试图做这样的事情: -

app_sc = sc;

但编译器给出了编译时错误。 我可以这样做,类似这样: -

 app_sc.low = sc & 0xFFFFFFFF;
 app_sc.high = (sc>>32) & (0xFFFFFFFF);

但是这可以保证,它会适用于所有情况吗?

有没有更好的方法呢?

5 个答案:

答案 0 :(得分:5)

使用一个不太旧的编译器支持一个合理的最新C标准(可能是C99,甚至可能更早),你应该有一个<stdint.h>标题给你一个类似int64_t的类型(对于一个有符号的64位整数)或uint64_t(对于无符号的64位整数),正好是64位,即使在32位机器上也是如此。

如果你的编译器没有它,我强烈建议升级你的编译器。您可以使用GCC(除非您有一个非常奇怪的目标架构,GCC不支持)。最新的GCC版本是4.7。

请注意,32位机器上的64位算术实际上需要一些编译器支持才能合理有效。 (例如,使用附带携带说明)。它不能仅通过库来完成,即使需要库来提供最复杂的操作(例如32位机器上的64位分区)。换句话说,对于32位机器,快速64位算术不能在C中进行可移植编码。

对于更大的数字,请考虑使用任意精度数字(称为 bigints),例如通过GNU gmp库。这些库使用非平凡的算法(所以即使数学也很困难,你可以通过发明有竞争力的bigint实现来阅读整本书并获得博士学位。)

答案 1 :(得分:3)

首先,我同意尽可能使用stdint类型的建议,所以我会自己这样做。

其次,我能想到的唯一可能更便宜的转换方式是通过联合,比如

union Int64
{
    uint64_t val64;
    struct {
        uint32_t lo32;
        uint32_t hi32;
    };
};

union Int64 i64;
i64.val64 = sc;
app_sc.low = i64.lo32;
app_sc.high = i64.hi32;

注意事项

  • 如果这样做涉及商店并重新加载(如图所示),它可能比你的逐位操作更昂贵
    • 如果您可以将现有的app_sc转换为此联合的实例(跳过32位加载),那么它可能是值得的
  • 或者,如果sc已经真正存储在内存中的某个位置,您可以将其地址转换为(union Int64 *)
    • 当然,如果sc目前已经分配了一个寄存器并且很脏,那么取走地址可能会强行存储
  • 原则上可以包装&amp;对齐问题,无论是现在还是随后的某些ABI
  • 这是依赖于体系结构的,因此后续端口可能意味着更改联合(我假设上面是x86 little-endianness)

坦率地说,这很脆弱,我希望这些警告显示出来。不过,这是另一种方式,你可以决定它是否也更好

答案 2 :(得分:1)

您的编译器,即使在32位机器上,也可能支持“long long int”。试试吧?

答案 3 :(得分:1)

您可以使用头文件stdint.h来使用有符号/无符号变量uint64_t / int64_t / ... uint8_t / int8_t 为了更好的解释:http://pubs.opengroup.org/onlinepubs/007904975/basedefs/stdint.h.html

答案 4 :(得分:0)

通过32位和64位架构,改变的是指针的大小,因此无符号long long将在32位中以与64位相同的方式工作。