当在c中调用变量参数函数时,整数参数被提升为int,浮点参数被提升为double
由于原型未指定可选参数的类型,因此在对可变参数函数的调用中,对可选参数值执行默认参数提升。这意味着
char
或short int
类型的对象(无论是否已签名)会酌情提升为int
或unsigned int
;并且float
类型的对象被提升为double
类型。因此,如果调用者将char
作为可选参数传递,则会将其提升为int
,并且该函数可以使用va_arg (ap, int)
访问它。
int
类型应该是32位机器上的4字节和64位机器上的8字节,是吗?
所以我想知道当我将long long int
传递给类似printf的变量参数函数%lld
格式时附加的内容。
而且,我再次想知道当我将long double
变量传递给带有%Lf
格式的printf时(无论是在32位还是64位机器上),会附加什么。
[被修改
在32位机器上,我试过这个:#include <stdio.h>
int main(void)
{
printf("sizeof(int) %d\n", sizeof(int));
printf("sizeof(long int) %d\n", sizeof(long int));
printf("sizeof(long long int) %d\n", sizeof(long long int));
printf("%lld\n", 1LL<<33);
printf("sizeof(float) %d\n", sizeof(float));
printf("sizeof(double) %d\n", sizeof(double));
printf("sizeof(long double) %d\n", sizeof(long double));
return 0;
}
结果是:
sizeof(int) 4
sizeof(long int) 4
sizeof(long long int) 8
8589934592
sizeof(float) 4
sizeof(double) 8
sizeof(long double) 12
这让我觉得并非所有参数都被提升为int
,否则我会打印0而不是8589934592。
也许只有小于int
的参数才会提升为int
。类似的东西可能适用于浮点类型。
[被修改
在64位机器上运行:
int main(void)
{
printf("sizeof(int) %lu\n", sizeof(int));
printf("sizeof(long) %lu\n", sizeof(long));
printf("sizeof(long long) %lu\n", sizeof(long long));
return 0;
}
并获取
sizeof(int) 4
sizeof(long) 8
sizeof(long long) 8
如果我完全理解标准,则只有char
和short
被提升为int
。我想知道在较小的架构中会发生什么,例如16位或8位MCU。我认为int
大小取决于体系结构,但我想知道{8}架构上sizeof(int)
是否可以是1。在这种情况下,除非丢失一些内容,否则无法将short
升级为int
答案 0 :(得分:9)
&#34; int
类型应该是32位机器上的4字节和64位机器上的8字节,是吗?&#34;不是。根据标准,int
s must be at least 16 bits in width (§5.2.4.2.1),但没有进一步的规定。
当您将long long int
传递给printf()
时,不受the integer promotions (§6.3.1.1 2)的限制:
无论是int还是unsigned,都可以在表达式中使用以下内容 可以使用int:
- 具有整数类型(int或unsigned int除外)的对象或表达式,其整数转换等级小于或等于 int和unsigned int的等级。
- _Bool,int,signed int或unsigned int类型的位字段。
如果int可以表示原始类型的所有值(限制为 通过宽度,对于位字段),该值被转换为int; 否则,它将转换为unsigned int。这些被称为 整数提升.58)所有其他类型的整数不变 促销强>
如果您将long double
传递给printf()
no conversion is made (§6.5.2.2 6):
如果表示被调用函数的表达式具有类型 不包括原型,执行整数促销 每个参数和类型为float的参数都被提升为 双。这些被称为默认参数促销。
与printf()
语句中的参数对应的转换说明符与这些促销和转换无关,除非在说明符及其对应参数的类型不匹配的情况下存在未定义的行为。 / p>
因此,执行整数提升,float
转换为double
,但"No other conversions are performed implicitly" (§6.5.2.2 8)。
解决您对问题的修改:&#34;这让我觉得并非所有参数都提升为int
。&#34;正确。只有整数转换的整数类型排名&#34;小于或等于int
和unsigned int
&#34的排名;受整数提升。浮点类型更简单; float
被提升为double
。就是这样。
值得指出的是,根据§6.2.5 10,有三种实际浮点类型float
,double
和long double
。 float
可能持有的值是double
可能持有的值的子集,而long double
又是long double
可能持有的值的子集。 }。因此,long long int
类型无法晋升。
此外,根据§6.3.1.1 1:
long long int的等级应大于long int的等级, 它应大于int的等级,它应该更大 比短的int的等级,它应该大于等级 签名char。
因此,long int
或int
不可能被提升为unsigned int
或short
。
至于你最后的担心,在某些实现中,int
升级到int
可能不会丢失一些比特,但请注意§6.2.5 8保证short
}}必须能够包含int
,因为short
的转化排名必须大于volatile int flag1;
...
的转化排名:
对于具有相同签名和不同的任何两个整数类型 整数转换等级(见6.3.1.1),类型的值范围 具有较小整数转换等级是值的子范围 另一种。
答案 1 :(得分:3)
int类型应该是32位机器上的4字节和64位机器上的8字节,是吗?
可能不是。首先,C不保证int
的大小,除了声明它必须至少2个字节(能够至少保持值2 ^ 16/2 - 1 = 32767)。 C中没有任何内容可以防止int
为8个字节,但这不太方便。
惯例是:所有8位和16位计算机都使用16位int
。所有其他计算机使用32位int
。这是行业事实上的标准。任何与这种惯例的偏差都是非常奇特的,尽管理论上允许C。
所以我想知道当我将long long int传递给类似printf with%lld格式的变量参数函数时会追加什么。
你得到一个很长的int。没有促销,因为变量不是上述小类型之一。使用的格式说明符与促销规则无关。
这让我觉得并非所有参数都被提升为int
事实上。仅提升标准提及的类型。可以在C11 6.5.2.2/6中找到默认参数促销的正式定义:
...对每个参数执行整数提升,并且 具有float类型的参数被提升为double。这些是 称为默认参数促销。
意味着只提升小整数类型(参见整数提升规则)和float
。没有其他类型。
为什么您认为打印各种类型尺寸的示例与默认参数促销有关,我不知道。
答案 2 :(得分:1)
所以我想知道当我将
pipeline { agent any parameters { string(name: 'PARAM1', description: 'Param 1?') string(name: 'PARAM2', description: 'Param 2?') } stages { stage('Example') { steps { echo "${params}" script { def myparams = currentBuild.rawBuild.getAction(ParametersAction).getParameters() build job: 'downstream-pipeline-with-params', parameters: myparams } } } } }
传递给变量时会追加什么 参数函数类似于带有long long int
格式的printf。而且,我想知道 将%lld
变量传递给带有long double
的printf时附加的内容 格式(无论是在32位还是64位机器上)。
没有任何事情发生,因为%Lf
必须至少与long long int
大小相同。即使在最多的&#34; pesimistic&#34;场景,其中int
,参数仍然传递&#34;原样是&#34; (没有任何促销)。这同样适用于sizeof(long long int) == sizeof(int)
。