使用整数常量的宏初始化对象
Initializing objects with macros for integer constants
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
7.20.4 引入了 宏整数常量 和:
1 The following function-like macros expand to integer constants
suitable for initializing objects that have integer types
corresponding to types defined in <stdint.h>. Each macro name
corresponds to a similar type name in 7.20.1.2 or 7.20.1.5.
这段我不太明白。
宏基本上将适当的后缀添加到无后缀的数字上,如:
UINT64_C(0x123) => 0x123ULL
但是如果我想初始化一个 uint64_t,我会这样做:
uint64_t x = 0x123;
而且我根本不会为后缀烦恼。
为什么我在初始化时需要这些宏?
UINT64_C(0x123)
宏创建一个立即数 unsigned long long
数字,因此它可以用于变量参数函数中,例如实例或中间计算,而无需转换为 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 位整数。一些平台通过定义 unsigned long long
来提供它,其他平台通过 unsigned long
来提供它。如果您的值要与需要此信息的函数进行互操作(例如 printf 和 pals),您应该处理此间接以获得灵活的代码。
在您的示例中 (uint64_t ex = 0x123;
) 类型具有此信息,无需显式调用宏。但我假设你需要所有 64 位,如果它超过 int
值,你应该有 UL
/ ULL
后缀。示例:
unsigned ex = 0x100000000U;
// warning: large integer implicitly truncated to unsigned type [-Woverflow]
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 7.20.4 引入了 宏整数常量 和:
1 The following function-like macros expand to integer constants suitable for initializing objects that have integer types corresponding to types defined in <stdint.h>. Each macro name corresponds to a similar type name in 7.20.1.2 or 7.20.1.5.
这段我不太明白。 宏基本上将适当的后缀添加到无后缀的数字上,如:
UINT64_C(0x123) => 0x123ULL
但是如果我想初始化一个 uint64_t,我会这样做:
uint64_t x = 0x123;
而且我根本不会为后缀烦恼。
为什么我在初始化时需要这些宏?
UINT64_C(0x123)
宏创建一个立即数 unsigned long long
数字,因此它可以用于变量参数函数中,例如实例或中间计算,而无需转换为 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 位整数。一些平台通过定义 unsigned long long
来提供它,其他平台通过 unsigned long
来提供它。如果您的值要与需要此信息的函数进行互操作(例如 printf 和 pals),您应该处理此间接以获得灵活的代码。
在您的示例中 (uint64_t ex = 0x123;
) 类型具有此信息,无需显式调用宏。但我假设你需要所有 64 位,如果它超过 int
值,你应该有 UL
/ ULL
后缀。示例:
unsigned ex = 0x100000000U;
// warning: large integer implicitly truncated to unsigned type [-Woverflow]