我想把3个整数(即每一个21位)存储在一个 long int
与这些宏。
typedef long int Triple;
#define TR_A(o) ((int)((o & 0x7FFFFC0000000000) >> 42))
#define TR_B(o) ((int)((o & 0x000003FFFFE00000) >> 21))
#define TR_C(o) ((int)(o & 0x00000000001FFFFF))
#define MK_TR(a,b,c) ((long int)((a<<42) & (b<<21) & c))
所以我们的想法是 o
是64位,而 a
,b
,c
各为32个。当存储在 o
它们是21位,64位是空位。a
, b
,然后 c
.
我得到一堆这样的错误。
warning: left shift count >= width of type [-Wshift-count-overflow]
#define MK_TR(a,b,c) ((long int)((a<<42) & (b<<21) & c))
^
能否在里面添加一些东西 TR_A
TR_B
TR_C
其中规定 o
是长?
有什么更好的方法吗?
我希望能够将这些值作为简单的值返回,而不是指针。在PC上使用Linux。
为了支持+- 1M范围内的两补号有符号的ints,需要进行掩码和移位。
inline uint64_t make64(int a, int b, int c) {
return ((uint64_t) (a & 0x1fffff) << 42) |
((uint64_t) (b & 0x1fffff) << 21) |
((uint64_t) c & 0x1fffff)
当拆分时,12个符号位将需要被恢复。
inline int32_t get_a(uint64_t t) {
return (int32_t)((t >> 42 & 0xfffff) | (t & 0x4000000000000000) ? 0xfff00000 : 0);
etc.
你可以指定一个整数文字(常数)应该被解释为一个... long int
加上 L
后缀(或小写 l
- 但这看起来太像一个 1
为了我的舒适)。) 同样,对于一个 long long int
,添加 LL
后缀。
在你的宏的情况下,你还需要显式地投掷参数。a
, b
和 c
到适当的(long
或 long long
)类型。
然而,与其依靠特定的编译器来实现 long int
作为64位类型(许多编译器没有这样做,而是使用32位类型来处理 int
和 long int
并要求 long long int
对于64位类型),你应该使用位宽的 特定 中定义的类型。<stdint.h>
头文件。
因此,下面的代码应该是无警告的 和便携式:
#include <stdint.h>
typedef int64_t Triple;
#define TR_A(o) ((int32_t)(((int64_t)(o) & 0x7FFFFC0000000000LL) >> 42))
#define TR_B(o) ((int32_t)(((int64_t)(o) & 0x000003FFFFE00000LL) >> 21))
#define TR_C(o) ((int32_t)((int64_t)(o) & 0x00000000001FFFFFLL))
// EDIT/NOTE: I have changed the bitwise & operations to | in the macro below,
// as this is probably what you actually want (otherwise it will give 0 always)!
#define MK_TR(a,b,c) ((int64_t)(((int64_t)(a) << 42) | ((int64_t)(b) << 21) | (int64_t)(c)))
另外,最好的做法是始终把宏参数放在括号里(如 (c)
在上面最后一行)。) 如果没有这个功能,对您的宏的调用就会出现一个带有 表情 作为一个论据,可能会给你带来意想不到的结果,这可能是难以追踪的。这将是一个很好的例子。
int a = 1, b = 2, c = 3;
Triple test = MK_TR(a + 1, b + 1, c + 1); // Unexpected(?) result.