在 Linux 中操作 u64 类型

发布于 2024-11-02 08:42:03 字数 420 浏览 0 评论 0原文

我们如何在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)

任何建议表示赞赏。非常感谢!

How can we manipulate the 32 bits high order and 32 bits low order of u64 type in Linux kernel. I tried this one, but the compiler reported a lot of warnings.

#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)

Any suggestions are appreciated. Thank a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

¢蛋碎的人ぎ生 2024-11-09 08:42:03

我怀疑,首先,您将需要对那些大的十六进制数字进行限定符,类似于:

0xffffffff00000000ULL

未修饰的整数常量属于 int 类型,这可能不足以保持给定的值。

除此之外,您应该发布您收到的警告,这样我们就不必玩心灵调试游戏:-)


还有一件事可能有问题是 v << 32 表示 32 位 v。我可能会选择类似的东西:

#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)

这将确保在进行任何位移之前一切都是正确的类型。请记住,这是未经测试的,您必须确认正确的行为。


但是,当然,我错过了尼古拉斯·奈特在评论中提出的最明显的解决方案。完全摆脱宏。这是由函数处理得更好的事情(如果你愿意的话可以标记为内联,但我很少发现这是必要的,因为 gcc 反正优化得非常好)。

这样,编译器就可以强制数据类型,并且您不会遇到使用 #define SQR(x) ((x)*(x))等宏总是遇到的问题i = SQR(j++)。

I suspect, for a start, that you're going to need qualifiers on those big honkin' hex numbers, something along the lines of:

0xffffffff00000000ULL

Unadorned integer constants are of the int type and that's probably not enough to hold the given values.

Other than that, you should post the warnings you're getting so we don't have to play the Psychic Debugging game :-)


And one other thing that may be problematic is v << 32 for a 32-bit v. I'd probably opt for something like:

#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)

This would make sure that everything is of the correct type before doing any bit shifting. Keep in mind that's untested, you'll have to confirm the correct behaviour.


But, of course, I missed the most obvious solution as put forward by Nicholas Knight in a comment. Get rid of the macros altogether. This is something far better handled by functions (marked inline if you wish but I rarely find this necessary since gcc optimises things insanely well anyway).

This way, the compiler can coerce data types and you don't run into the problems you invariably do with macros like #define SQR(x) ((x)*(x)) and i = SQR(j++).

べ繥欢鉨o。 2024-11-09 08:42:03

正如其他人已经说过的,正确的 typedef 是 uint64_t。该类型的常量可以通过预定义宏UINT64_C 获得,例如UINT64_C(1) 可能会产生1ULL。但实际上我认为你不需要这些。

如果您确实有该类型的变量(即固定宽度 64 且无符号),以 32 位移位两次应该总是给出正确的结果。仅具有高位

((a >> 32) << 32)

编译器会将其优化为适合您平台的完美汇编器。 (对于 gcc,使用 -march=native 进行编译,并使用 -S 检查汇编器。)

要确保这确实是一个 uint64_t 最好的确实像别人说的有功能。然后它会转换为正确的类型,您不必担心。

如此小的函数定义属于头文件,因此您必须要么将其声明为内联(或静态,如果你必须),否则你会在链接时遇到“多重定义符号”错误。

要在某处声明函数的符号,您必须在一个编译单元中放置一个 extern inline 声明(而不是定义)。

As already said by others, the correct typedef is uint64_t. Constants of that type can be obtained by the predefined macro UINT64_C, e.g UINT64_C(1) will probably result in 1ULL. But actually I don't think you need these.

If you really have a variable of that type (i.e with fixed width 64 and unsigned) shifting twice with 32 bit should always give the correct result. To only have the high order bits

((a >> 32) << 32)

The compiler will optimize this to the perfect assembler for your platform. (For gcc, compile with -march=native and check the assembler with -S.)

To be sure that this is really an uint64_t best is really as others said to have a function. This then converts to the right type(s), and you don't have to worry.

Such a small function definition belongs in a header file, so you must either declare it inline (or static if you must), otherwise you will encounter "multiply defined symbol" errors at link time.

To also have a symbol declared of your function somewhere, you'd have to put an extern inline declaration (not definition) in exactly one compilation unit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文