提问者:小点点

使用整数常量的宏初始化对象


http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 7.20.4 引入了宏整数常量,如下所示:

1 以下类似函数的宏扩展为整数常量,适用于初始化具有与 中定义的类型对应的整数类型的对象

我不太明白这一段。宏基本上将适当的后缀拍打到无后缀的数字上,如下所示:

UINT64_C(0x123) => 0x123ULL

但是如果我想初始化一个uint64_t,我会做:

uint64_t x = 0x123; 

而且我根本不会打扰后缀。

为什么在初始化中需要这些宏?


共2个答案

匿名用户

UINT64_C(0x123) 宏创建一个即时无符号的长长数字,因此它可以用于变量参数函数,例如或中间计算,而无需转换为 uint64_t 类型,其中使用此特定数据类型很重要。

例:

printf("%llu\n",UINT64_C(0x123));

是正确的

printf("%llu\n",0x123);

不正确且是未定义的行为,因为数据大小不正确,而 printf 通常不知道这一点。

当您使用 uint64_t x = 0x123; 时,存在赋值和隐式转换,因此无需执行此操作(printf(“%llu\n”,x); 是正确的)。

另一种用法是在中间计算中,如下图所示:

uint32_t a = 0xFFFFFFFF;
uint64_t x = a + UINT64_C(0xFFFFFFFF);

将产生完整的 64 位总和,而

x = a + 0xFFFFFFFF;

将在 32 位内换行,因为中间结果使用 uint32_t 类型。

UINT64_C(SOME_CONSTANT) 和 (uint64_t) SOME_CONSTANT之间的区别在于,如果值对于UINT64_C来说太大,则第一种情况将在更广泛的类型中生成具有指定值的常量,第二种情况将生成转换为命名类型的值。这些可能导致哪些错误以及编译器是否会诊断问题可能取决于上下文。

匿名用户

使用 u64,您可以告诉您想要 64 位整数。一些平台通过定义无符号长长来提供它,其他平台通过定义无符号长整型来提供它。如果你的值要与需要此信息的函数(例如 printf 和 pals)进行互操作,你应该处理这种间接寻址以获得灵活的代码。在您的示例中 (uint64_t ex = 0x123;) 类型具有此信息,无需显式调用宏。但我假设你需要所有的 64 位,如果它超过 int 值,你应该有 UL / ULL 后缀。例:

unsigned ex = 0x100000000U;
// warning: large integer implicitly truncated to unsigned type [-Woverflow]