每个
printf
格式说明符都需要某种特定类型的参数。
"%d"
需要一个
int
类型的参数;
"%u"
需要一个
unsigned int
类型的参数。你完全有责任传递正确类型的参数。
unsigned int i = -12
-12
是类型为int
的。初始化会自动将该值从int
转换为unsigned int
。转换后的值(为正且非常大)存储在i
中。如果int
和unsigned int
都是32位,则存储的值将是4294967284
(232-12)。
printf(" i = %d\n",i);
i
的类型为 unsigned int
,但是 "%d"
需要一个 int
类型的参数。这种行为在 C 标准中没有定义。通常情况下,存储在 i
中的值将被解释为存储在一个 int
对象中。在大多数系统上,输出将为 i = -12
,但您不应该依赖于此。
printf(" i = %u\n",i);
假设之前的语句未造成混乱,这样代码将会正确打印i
的值。
对于普通函数而言,如果你调用它们时传入的参数类型不匹配,编译器通常会自动进行隐式转换以适应该参数声明的类型。但是对于像printf
这样的可变参数函数,由于编译器无法知道参数期望的类型,因此无法进行隐式类型转换。相反,参数将遵循默认参数提升规则进行处理。如果一个参数类型比int
更窄,且int
能够容纳该类型的所有值,则该参数将被提升为int
,否则将被提升为unsigned int
。如果参数类型为float
,则将其提升为double
(这也就是为什么"%f"
可以同时用于float
和double
类型的参数)。
这些规则意味着,一个窄的无符号类型参数通常(但并非总是)会被提升为(有符号)int
。
unsigned char a=200, b=200, c;
假设每个字节都是8位,a
和 b
被设置为 200
。
c = a+b
和 unsigned char
类型相比,总和 400
太大了。对于无符号算术和转换,超出范围的结果将被减少到类型的范围内。c
被设置为 144
。
printf("result=%d\n",c);
尽管参数是无符号类型,c
的值被提升为int
类型;int
可以容纳该类型的所有可能值。 输出结果为result=144
。