的整数转换等级long
需要大于int
(6.3.1.1p1) 的等级,因此即使具有与 相同的表示(和精度)va_arg(args, long)
也是必需的。请注意,在大多数 64 位平台上,是 64 位;Windows(一个 LLP64 平台)是一个例外。 long
int
long
size_t
要求为无符号整数类型(6.5.3.4p5,7.19p2),建议整数转换秩不大于long int
(7.19p4);要求其精度至少为 16 位(7.20.3p2,最小值SIZE_MAX
)。它不需要是(typedef to a)标准整数类型,尽管它是允许的。
那么 的整数转换等级有三种可能性size_t
:
- 它小于 的
int
,因此size_t
参数将被提升为int
(如果 的精度size_t
小于 的int
)或unsigned int
(如果两种类型具有相同的精度)。无论哪种情况,您都需要编写va_arg(args, unsigned int)
(即使size_t
参数被提升为int
,7.16.1.1p2 也允许使用等效的无符号类型)。
- 与 的相同
int
,即size_t
与 的类型相同unsigned int
。在这种情况下,要么 要么va_arg(args, unsigned int)
被va_arg(args, size_t)
允许。
- 它大于
int
。在这种情况下va_arg(args, size_t)
必须使用。
请注意,即使 的精度与 的精度size_t
相同,也可以获得 1 和 3 中的任何一个int
。
这意味着要size_t
使用 提取参数va_arg
,必须知道或推断 的整数转换等级size_t
。这可以使用类型泛型宏 (6.5.1.1) 来完成:
#define va_arg_size_t(args) _Generic((+(sizeof(0))), \
int: (size_t) va_arg((args), unsigned int), \
unsigned int: (size_t) va_arg((args), unsigned int), \
default: va_arg((args), size_t))
如果由上面使用的一元加号运算符size_t
提升为int
,那么我们提取一个unsigned int
; 如果size_t
提升为unsigned int
,或者是 typedef unsigned int
,那么我们提取一个unsigned int
; 如果它没有被提升并且是与 不同的类型unsigned int
,那么我们就成功了default
。我们不能将size_t
自身作为选项提供,因为如果size_t
是 typedef for会发生冲突unsigned int
。
请注意,这是一个不限于 的问题size_t
,ptrdiff_t
并且wchar_t
具有相同的问题(对于后者,wint_t
可以保持任何wchar_t
值并且不受提升,但不能保证提升到,与提升到 的保证wchar_t
不同)。我建议标准需要为. (当然,你可以像上面那样使用,但它是在脖子上的痛苦。)wint_t
char
int
spromo_t
ppromo_t
wpromo_t
stdint.h
_Generic