[英]Promotions and conversions of variables in printf()
在这种情况下,
#include <stdio.h>
int main()
{
unsigned char a = 1;
printf("%hhu", -a);
return 0;
}
printf 中的参数-a
通过一元减号运算符的printf
提升提升为int
,随后通过默认参数提升提升,最后通过格式说明符转换为unsigned char
。
所以-a
=> -(int)a
(by ~
) => function call => (unsigned char)-(int)a
(by %hhu
) 没有转换。 我的想法对吗?
你是正确的a
在-a
中被提升为int
,并且printf("%hhu", -a);
将int
传递给printf
。 使用%hhu
执行的名义转换不清楚。
请注意,如果a
不为零,则-a
会生成一个不是unsigned char
值的值(在int
中)。 此外,对于二进制补码 8 位有signed char
,如果a
大于 128,则-a
生成一个不是有signed char
值的值。
要了解%hhu
,我们查看 C 2018 7.21.6.1 8 中u
的规范:
unsigned int
参数转换为无符号八进制 (o)、无符号十进制 (u)、...
对于 7.21.6.1 7 中的hh
:
指定后面的 d、i、o、u、x 或 X 转换说明符适用于有
signed char
或unsigned char
参数(该参数将根据 integer 提升,但其值应转换为有signed char
或打印前的unsigned char
);…
首先我们要解决“ signed char
or unsigned char
”这个问题。 这是否表示我们可以为%hhu
传递一个有signed char
或unsigned char
? 我想不是; 我认为作者刚刚将%hhd
(用于转换有signed char
)和%hhu
(用于转换unsigned char
)的语言放在一起。 所以我相信目的是应该为%hhu
转换规范传递一个提升的unsigned char
。
Apple Clang 11.0.0 似乎同意,当传递-a
(但不是a
)时,它警告:“警告:格式指定类型'unsigned char'但参数的类型为'int' [-Wformat]”
如上所述,传递-a
可能传递的值不能由传递提升的unsigned char
产生。 它甚至可以传递一个不能通过传递提升的有signed char
或unsigned char
而产生的值。 在这种情况下,可以说我们违反了传递unsigned char
的要求,因此 C 标准没有指定结果行为。 尽管它说传递的值应转换为unsigned char
,但我认为这是一种名义上的转换,而不是对库实现的特定要求,这也属于“好像”规则:它实际上没有如果程序的结果定义行为相同,则执行。 但是,由于可能未定义传递不正确的值,因此我们没有定义的行为。
这可能是对规则的严格阅读,但如果printf
在a
为 1 时打印“4294967295”而不是“255”,我不会感到惊讶。
printf
是可变参数 function。 ...
参数传递的 arguments 的类型在 function 内部未知。 因此,任何可变参数 function 必须依赖其他机制来解释va_arg
的 arguments 的类型。 printf
和家人使用const char* format
字符串“告诉他们”通过了哪种 arguments。 传递与其格式说明符指定的预期类型不同的类型会导致未定义的行为。
例如:
printf("%f", 24)
是未定义的行为。 在任何地方都没有从int
到float
的转换,因为 arguments 按原样传递(在提升之后),并且在printf
内部 function 错误地将其第一个参数视为float
。 printf
不知道也无法知道参数的真实类型是int
。
Variadic arguments 进行了一些自己的促销活动。 对您的问题感兴趣的unsigned char
被提升为int
或unsigned int
(我不确定 tbo)。 因此,可变参数实际上无法为unsigned char
类型。 所以hhu
虽然确实是unsigned char
的说明符,但它实际上会期望一个unsigned int
( int
),这就是你传递给它的内容。
所以 afaik 代码是安全的,因为由一元减号和传递可变参数 arguments 引起的两个 integer 促销活动。 不过,我不是 100% 确定。 Integer 促销活动诡异而复杂。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.