c - 在宏(或其他东西)中指定 int 大小

标签 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))
#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。

最佳答案

您可以指定整数文字(常量)应解释为 long int通过添加 L后缀(或小写 l - 但为了我的舒适,这看起来太像 1)。同样,对于 long long int ,添加 LL后缀。

对于您的宏,您还需要显式转换参数,a , bc到适当的( longlong long )类型。

但是,与其依赖特定的编译器来实现 long int作为 64 位类型(许多编译器没有,并且 intlong int 都使用 32 位,并且需要 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.

关于c - 在宏(或其他东西)中指定 int 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61875304/

相关文章:

c# - 我是否正确调用了这个 C++ DLL?

javascript - Javascript 对 64 位浮点的 native 支持

c - PostgreSQL C 函数输出一组记录时出现语法错误

c++ - 在 C++ 中获取 double 的精确位表示

scala - Scala 中变量的返回类型

.Net 3.5 Windows 窗体应用程序 : x86 vs x64 load times on 64 bit Vista

ios - 如何使用 GPUImage 启用 64 位支持

sql - 使用 PostgreSQL libpqtypes PQputf 或 PQexecf 函数将 SQL null 作为 SQL 语句参数值传递

c - 如何获取C中所有驱动器的列表

c - 用户输入无效号码时不会出现错误消息