首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当通过省略号发送时,‘`long`’和`size_t`的整数提升?

当通过省略号发送时,‘`long`’和`size_t`的整数提升?
EN

Stack Overflow用户
提问于 2012-10-13 00:01:17
回答 3查看 1.7K关注 0票数 3

从实施printf的人的角度来看待这个问题。

因为printf的参数是通过省略号(...)传递的,所以它们会被整数提升。我知道charshortint会升职到int,而long long不会升职。它们的unsigned对应物也是如此。

这意味着在读取变量时,charshortint应使用va_arg(args, int),而long long应使用va_arg(args, long long)

我的问题是,longsize_t会升职吗?如果升职了,升职是什么?在互联网上有很多关于整数促销的资源,但我还没有看到任何关于这些类型的讨论。

附言:如果您能参考该标准,我将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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的整数转换秩有三种可能

  1. 它小于int的精度,因此size_t参数将被提升为int (如果size_t的精度小于int的精度)或unsigned int (如果两种类型的精度相同)。在任何一种情况下,您都需要编写va_arg(args, unsigned int) (即使size_t参数被提升为int,但7.16.1.1p2).
  2. It允许使用等效的无符号类型与int相同,即size_tunsigned int是同一类型。在这种情况下,允许使用va_arg(args, unsigned int)va_arg(args, size_t)
  3. 它大于int。在这种情况下必须使用va_arg(args, size_t)

请注意,即使size_t的精度与int的精度相同,也可以获得1和3中的任何一个。

这意味着要使用va_arg提取size_t参数,必须知道或推断size_t的整数转换秩。这可以使用类型泛型宏(6.5.1.1)来完成:

代码语言:javascript
复制
#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_tunsigned int的类型定义函数,就会发生冲突。

请注意,这不仅仅是size_t的问题,ptrdiff_twchar_t有相同的问题(对于后者,wint_t可以持有任何wchar_t值,并且不受提升的影响,但不能保证wchar_t提升到wint_t,不像保证char提升到int)。我建议该标准需要引入新的类型spromo_tppromo_twpromo_t,对于stdint.h中的类型也是如此。(当然,您可以像上面那样使用_Generic,但这是一个令人头疼的问题。)

票数 2
EN

Stack Overflow用户

发布于 2012-10-13 00:13:12

C说(强调我的):

(C99,6.3.1.1p2)“只要可以使用整型或无符号整型,就可以在表达式中使用以下内容:

-整数类型的对象或表达式,其整数转换秩小于或等于int和unsigned int的秩。

- _Bool、整型、带符号整型或无符号整型的位域。

如果int可以表示原始类型的所有值,则将该值转换为int;否则,将其转换为无符号int。这些被称为整数提升。48)所有其他类型都不会因整数提升而改变。

票数 2
EN

Stack Overflow用户

发布于 2012-10-13 00:51:37

long类型的参数将不会被提升。与size_t相关的整数促销可以总结如下:

  1. 如果size_tint的范围内,则promote to int
  2. if size_tint的范围内,promote to int
  3. ifsize_t具有比unsigned int更大的转换等级(因此宽度),并且不会发生升级

最简单的情况是如果size_tunsigned int的别名,或者size_t的宽度比The大。在这些情况下,不会发生提升,您可以使用size_t读取变量参数。

边缘情况是

  • size_tint
  • size_t的范围内不在int的范围内,但在没有实际为unsigned int

unsigned int范围内

如果int包含padding of,如果size_t是宽度与unsigned int相同的扩展整数类型,则会发生后一种情况。

假设整数表示不包含填充位,您可以通过读取unsigned int可变参数来涵盖这两种边缘情况,这将适用于所有合理的C语言实现,尽管可能存在未定义的行为。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12862966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档