关于C风格省略号和printf族参数大小规范的实际含义的问题



据我所知,当将值传递给包含有C风格省略号的函数参数时,这些值可能会被提升。

  1. signed/unsignedcharshort分别晋升为signed/unsignedint
  2. float升级为double

维基百科的可变参数页面也符合以下条件:

boolcharshort和无范围枚举转换为int或更宽的整数类型,如整数提升

(强调矿(

我不太清楚或更宽的整数类型的实际含义。如果long的长度大于int,那么它就等于long,或者这只是说明这是编译器上实现定义的行为?

没有说明的是其他更大的类型会发生什么,例如long longlong double,如果它比编译器上的int长,可能还会发生long。我假设它们是按原样通过的,这是有道理的,但对此事没有明确的声明。

假设较大的类型按原样传递,那么对于较大的类型,大小规范是有意义的。但是,较小的类型呢?维基百科的长度字段页面声明:

hh-对于整数类型,导致printf期望一个int大小的整数参数,该参数是从char升级而来的。

h-对于整数类型,导致printf期望从short升级而来的int大小的整数参数。

我认为整数类型应该替换为积分类型TBH,但忽略了这一点,如果编译器已经进行了任何适用的升级,并且函数已经丢失了对这些类型的跟踪,那么从XXX升级的预期int侧整数参数实际上意味着可能升级的int侧整数参数,不管它是从什么升级的,并且它会将它截断为指定的大小。

这是什么意思吗?

尽管具体得令人尴尬,但在每个有用的执行模型中,它们都是可以推送到堆栈上的最小大小的项。在每个重要的情况下,它都对应于机器的本地字大小:32位CPU:32位堆栈元素;64位CPU:64位堆栈元素。

可变C函数自变量由单词大小和对齐的对象组成:

  1. 较小的项目会扩展到文字大小
  2. 较大的项目与文字大小对齐

所以,如果我调用了一个带参数的变元函数:

(short a, char b, long c, struct { int a; long b; } d)

在单词大小与sizeof(int(相同的机器上它将被传递为:

(int a, int b, struct { int lo,hi; } c, union { struct { int a, long b }; int x[3] } d)

和一台单词大小与长度相同的机器:

(long a, long b, long c, union { struct { int a; long b; }; long x[2]; } d)

最新更新