在 C99 标准第 7.18.4.1 节“最小宽度整数常量的宏”中,一些宏定义为[U]INT[N]_C(x)
用于将常量整数转换为 N = 8、16、32、64 的最小数据类型。为什么要定义这些宏,因为我可以使用 L , UL, LL 或 ULL 修饰符?例如,当我想使用至少32 位无符号常量整数时,我可以简单地写42UL
而不是UINT32_C(42)
. 由于长数据类型至少为 32 位宽,因此它也是可移植的。
那么,这些宏的用途是什么?
你需要它们在你想确保它们不会变得太宽的地方
#define myConstant UINT32_C(42)
然后
printf( "%" PRId32 " is %s\n", (hasproperty ? toto : myConstant), "rich");
在这里,如果常量是UL
表达式,则可ulong
变参数函数可能会将一个 64 位的值放在堆栈上,这会被printf
.
它们使用宽度至少为 N的最小UINT32_C(42)
整数类型,因此仅相当于小于 32 位42UL
的系统。int
在int
32 位或更高位的系统上,UINT32_C(42)
等效于42U
. 你甚至可以想象一个系统,其中 ashort
是 32 位宽,在这种情况下,它UINT32_C(42)
等价于(unsigned short)42
.
编辑:@obareey 似乎大多数(如果不是全部)标准库的实现不符合标准的这一部分,也许是因为这是不可能的。[ glibc 错误 2841 ] [ glibc 提交 b7398be5 ]
宏本质上可能会在它们的参数中添加一个整数常量后缀,例如
L
, LL
, U
, UL
, o UL
,这基本上使它们几乎等同于相应的强制转换,除了后缀永远不会向下转换。
例如,
UINT32_C(42000000000)
LLP64 架构上的(420 亿)将变成42000000000U
,其类型UL
受此处解释的规则的约束。另一方面,相应的转换 ( (uint32_t)42000000000
) 会将其截断为uint32_t
(unsigned int
在 LLP64 上)。
我想不出一个好的用例,但我想它可以在一些需要至少 X 位才能工作的通用位旋转宏中使用,但如果用户传入某些东西,我不想删除任何额外的位大。