如何操作Linux内核中u64类型的32位高位和32位低位。我试过这个,但是编译器报告了很多警告。
#define HI_BYTES(_a) (_a & 0xffffffff00000000)
#define LO_BYTES(_a) (_a & 0x00000000ffffffff)
/* _v is 32 bit value */
#define HI_BYTES_SET(_a, _v) do {_a = (_a & 0x00000000ffffffff) | (_v << 32)} while (0)
#define LO_BYTES_SET(_a, _v) do {_a = (_a & 0xffffffff00000000) | (_v)} while (0)如有任何建议,欢迎光临。非常感谢!
发布于 2011-04-19 16:30:33
首先,我怀疑你需要对那些大的十六进制数字使用限定符,大概是这样的:
0xffffffff00000000ULL未修饰的整数常量是int类型,这可能不足以容纳给定值。
除此之外,你应该发布你得到的警告,这样我们就不用玩心理调试游戏了:-)
另外一个可能有问题的事情是32位v的v << 32。我可能会选择像这样的东西:
#define HI_BYTES(_a) (_a & 0xffffffff00000000ULL)
#define LO_BYTES(_a) (_a & 0x00000000ffffffffULL)
#define HI_BYTES_SET(_a, _v)\
do {\
u64 _xyzzy = _v;\
_a = (_xyzzy << 32) | LO_BYTES(_a)\
} while (0)
#define LO_BYTES_SET(_a, _v)\
do {\
u64 _xyzzy = _v;\
_a = HI_BYTES(_a) | (_xyzzy)\
} while (0)这将确保在进行任何位移位之前,所有内容都是正确的类型。请记住,这是未经测试的,您必须确认正确的行为。
但是,当然,我错过了Nicholas Knight在评论中提出的最明显的解决方案。完全去掉这些宏。这是由函数更好地处理的东西(如果你愿意,可以标记为内联,但我很少发现这是必要的,因为gcc无论如何都会疯狂地优化事情)。
这样,编译器就可以强制使用数据类型,而不会遇到像#define SQR(x) ((x)*(x))和i = SQR(j++)这样的宏经常遇到的问题。
发布于 2011-04-19 17:53:06
正如其他人已经说过的,正确的类型定义是uint64_t。这种类型的常量可以通过预定义的宏UINT64_C获得,例如UINT64_C(1)可能会导致1ULL。但实际上我不认为你需要这些。
如果你真的有一个这种类型的变量(即固定宽度为64,无符号的),用32位移位两次应该总是能给出正确的结果。只有高阶位
((a >> 32) << 32)编译器将对此进行优化,使其成为适合您的平台的完美汇编程序。(对于gcc,用-march=native编译,用-S检查汇编器)
要确定这真的是一个uint64_t最好的,就像其他人所说的那样,它真的有一个功能。然后,这将转换为正确的类型,您不必担心。
如此小的函数定义属于头文件,因此必须将其声明为inline (如果需要,则声明为static ),否则将在链接时遇到"multiply defined symbol“错误。
要在某个地方声明函数的符号,必须将extern inline声明(而不是定义)放在一个编译单元中。
https://stackoverflow.com/questions/5713576
复制相似问题