从实施printf的人的角度来看待这个问题。
因为printf的参数是通过省略号(...)传递的,所以它们会被整数提升。我知道char,short和int会升职到int,而long long不会升职。它们的unsigned对应物也是如此。
这意味着在读取变量时,char、short和int应使用va_arg(args, int),而long long应使用va_arg(args, long long)。
我的问题是,long和size_t会升职吗?如果升职了,升职是什么?在互联网上有很多关于整数促销的资源,但我还没有看到任何关于这些类型的讨论。
附言:如果您能参考该标准,我将不胜感激。
发布于 2012-10-13 01:16:45
long的整数转换秩要求大于int的秩(6.3.1.1p1),因此即使va_arg(args, long)具有与long相同的表示(和精度),也需要int。请注意,在大多数64位平台上,long是64位的;Windows ( LLP64平台)是一个例外。
size_t要求为无符号整数类型(6.5.3.4p5,7.19p2),建议整数转换秩不大于long int (7.19p4),精度要求至少为16位(7.20.3p2,SIZE_MAX的最小值)。它不需要是标准的整数类型,尽管它是允许的。
因此,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的精度与int的精度相同,也可以获得1和3中的任何一个。
这意味着要使用va_arg提取size_t参数,必须知道或推断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,或者是unsigned int的类型定义,那么我们提取unsigned int;如果它没有被提升,并且是与unsigned int不同的类型,那么我们将访问default块。我们不能将size_t本身作为一个选项提供,因为如果size_t是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,但这是一个令人头疼的问题。)
发布于 2012-10-13 00:13:12
C说(强调我的):
(C99,6.3.1.1p2)“只要可以使用整型或无符号整型,就可以在表达式中使用以下内容:
-整数类型的对象或表达式,其整数转换秩小于或等于int和unsigned int的秩。
- _Bool、整型、带符号整型或无符号整型的位域。
如果int可以表示原始类型的所有值,则将该值转换为int;否则,将其转换为无符号int。这些被称为整数提升。48)所有其他类型都不会因整数提升而改变。“
发布于 2012-10-13 00:51:37
long类型的参数将不会被提升。与size_t相关的整数促销可以总结如下:
size_t在int的范围内,则promote to intsize_t在int的范围内,promote to intsize_t具有比unsigned int更大的转换等级(因此宽度),并且不会发生升级最简单的情况是如果size_t是unsigned int的别名,或者size_t的宽度比The大。在这些情况下,不会发生提升,您可以使用size_t读取变量参数。
边缘情况是
size_t在intsize_t的范围内不在int的范围内,但在没有实际为unsigned int的unsigned int范围内
如果int包含padding of,如果size_t是宽度与unsigned int相同的扩展整数类型,则会发生后一种情况。
假设整数表示不包含填充位,您可以通过读取unsigned int可变参数来涵盖这两种边缘情况,这将适用于所有合理的C语言实现,尽管可能存在未定义的行为。
https://stackoverflow.com/questions/12862966
复制相似问题