C 使用整数常量的宏初始化对象
7.20.4引入了宏整数常量,包括: 1以下类似宏的函数扩展为整数常量 适用于初始化具有整数类型的对象 对应于中定义的类型。每个宏名称 对应于7.20.1.2或7.20.1.5中的类似类型名称 我不太明白这段话。 宏基本上会在未加后缀的数字上加上适当的后缀,如中所示:C 使用整数常量的宏初始化对象,c,macros,integer,c11,C,Macros,Integer,C11,7.20.4引入了宏整数常量,包括: 1以下类似宏的函数扩展为整数常量 适用于初始化具有整数类型的对象 对应于中定义的类型。每个宏名称 对应于7.20.1.2或7.20.1.5中的类似类型名称 我不太明白这段话。 宏基本上会在未加后缀的数字上加上适当的后缀,如中所示: UINT64_C(0x123) => 0x123ULL 但如果我想初始化uint64_t,我只需要执行以下操作: uint64_t x = 0x123; 而且我根本就不在乎后缀 为什么我在初始化时需要这些宏?此UINT
UINT64_C(0x123) => 0x123ULL
但如果我想初始化uint64_t,我只需要执行以下操作:
uint64_t x = 0x123;
而且我根本就不在乎后缀
为什么我在初始化时需要这些宏?此UINT64_C(0x123)
宏创建一个立即无符号长-长数字,因此它可以用于变量参数函数中,例如,或中间计算,而无需转换为UINT64_t
类型,使用此特定数据类型非常重要
例如:
printf("%llu\n",UINT64_C(0x123));
是正确的
printf("%llu\n",0x123);
不正确且为UB,因为数据大小不正确,printf
无法知道这一点
当您执行uint64\u t x=0x123时代码>,有一个赋值和一个隐式强制转换,所以不需要这样做(而且printf(“%llu\n”,x);
是正确的)
另一种用法是在中间计算中,如下所示:
uint32_t a = 0xFFFFFFFF;
uint64_t x = a + UINT64_C(0xFFFFFFFF);
不会溢出
x = a + 0xFFFFFFFF;
将溢出,因为中间结果存储在uint32\u t
总之,UINT64_C(SOME_常量)
和(UINT64_t)SOME_常量
之间的主要功能区别在于,如果值溢出,在第一种情况下肯定会得到警告,在另一种情况下会得到“转换”(可能是警告,但这取决于编译器).对于u64,您告诉我们您想要64位整数。一些平台通过定义无符号long
来提供它,其他平台通过无符号long
来提供它。如果您的值要与需要此信息的函数(例如printf和pals)进行互操作,则应处理此间接操作,以获得灵活的代码。
在您的示例中(uint64\u t ex=0x123;
)类型具有此信息,无需显式调用宏。但是我假设您需要所有的64位,如果它超过int
值,您应该有UL
/ULL
后置。例如:
unsigned ex = 0x100000000U;
// warning: large integer implicitly truncated to unsigned type [-Woverflow]
可能重复:我认为这些宏的引入只是为了克服语言缺陷,即stdint.h类型没有整数文字后缀。有点像inttypes.h中printf的格式说明符。您得到警告是因为赋值,而不是因为后缀。后缀从不向下倾斜。如果您printf(“%u\n”,0x100000000)代码>,您会收到一条关于格式字符串错误(不是截断)的警告。