C 在宏中指定整型大小(或其他)

C 在宏中指定整型大小(或其他),c,types,64-bit,bit,bit-shift,C,Types,64 Bit,Bit,Bit Shift,我试图用以下宏在一个long int中存储3个整数(即每个21位): 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)) #defin

我试图用以下宏在一个
long int
中存储3个整数(即每个21位):

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))
是否可以在
tru A
/
tru B
/
tru C
中添加指定
o
较长的内容

有更好的方法吗


我希望能够以简单值而不是指针的形式返回这些值。在PC上使用Linux。

您可以通过添加
L
后缀(或小写
L
,指定整数文本(常量)应解释为
long int
,但我觉得这太像
1
)。同样,对于
long-long-int
,添加
LL
后缀

对于宏,还需要显式地将参数、
a
b
c
转换为适当的(
long
long
)类型

但是,与其依赖特定编译器将
long int
实现为64位类型(许多编译器不这样做,并且对
int
long int
都使用32位,对于64位类型则需要
long long int
),您应该使用
头文件中定义的位宽度特定类型

因此,以下代码应无警告且可移植:

#包括
typedef int64_t三元组;
#定义TR_A(o)((int32_t)((int64_t)(o)和0x7ffffc000000000ll)>>42))
#定义TR_B(o)((int32_t)((int64_t)(o)和0x000003ffffefe0000ll)>>21))
#定义TR_C(o)((int32_t)((int64_t)(o)和0x00000000001fffffffll))
//编辑/注意:我已将下面宏中的按位&运算改为|,
//因为这可能是您实际想要的(否则它将始终为0)!

#定义MK_TR(a,b,c)((int64_t)((int64_t)(a)要支持+/-1M范围内的两个补码符号int,需要掩蔽和移位:

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)

使用一个有类型的函数,然后使用
uint\u 32t
int64\u t
,这样的类型就可以使它们在大小上独立于机器吗?@MichaelOrganger是的,我想这就是我需要做的。我只是觉得宏也应该可以这样做。我确信,如果你将每个元素类型转换为你想要的类型,这是可能的,但是太脆弱了。
((long int)(a))你说
a
是32位,所以
aIf你只是把它藏起来,你将来会给吹笛者更多的钱:)相信你的编译器,使用20年前创建的正确类型,现在就可以使用函数了。我也在使用旧的操作系统C级代码,所以我理解,但是技术债务会引起兴趣…或者只使用那些类型不符合要求的函数…@MichaeldOrgang。我理解C/C++C中有很多“反宏”的感觉社区,但OP确实问了一个关于宏的问题。就我个人而言,我也更喜欢这种情况下的函数。有(或可以有)还是宏的位置,别误会。但对于像这样的简单事情,尤其是类型导致不好的事情时,函数更好。@Fredrik,根据编造,我应该说没有指定-宏的威力:)对于右移的位,通常更喜欢
无符号long-long
。此外,将移位计数提升到
int64\t
也没有好处。C移位运算符(与其他运算符不同)不要求两个操作数具有相同的类型。在TR_A中只使用
>42
就可以了。@PeterCordes在第二个(非常好)点上,请参阅最新的编辑(使代码更简单)。在第一个点上:在要右移的内容中,MSB(符号位)总是被掩码清除,所以使用有符号整数应该不会有问题。
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)
inline int32_t get_a(uint64_t t) {
    return (int32_t)((t >> 42 & 0xfffff) | (t & 0x4000000000000000) ? 0xfff00000 : 0);
etc.