繁体   English   中英

printf()中变量的提升和转换

[英]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 charunsigned char参数(该参数将根据 integer 提升,但其值应转换为有signed char或打印前的unsigned char );…

首先我们要解决“ signed char or unsigned char ”这个问题。 这是否表示我们可以为%hhu传递一个有signed charunsigned 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 charunsigned char而产生的值。 在这种情况下,可以说我们违反了传递unsigned char的要求,因此 C 标准没有指定结果行为。 尽管它说传递的值应转换为unsigned char ,但我认为这是一种名义上的转换,而不是对库实现的特定要求,这也属于“好像”规则:它实际上没有如果程序的结果定义行为相同,则执行。 但是,由于可能未定义传递不正确的值,因此我们没有定义的行为。

这可能是对规则的严格阅读,但如果printfa为 1 时打印“4294967295”而不是“255”,我不会感到惊讶。

printf是可变参数 function。 ...参数传递的 arguments 的类型在 function 内部未知。 因此,任何可变参数 function 必须依赖其他机制来解释va_arg的 arguments 的类型。 printf和家人使用const char* format字符串“告诉他们”通过了哪种 arguments。 传递与其格式说明符指定的预期类型不同的类型会导致未定义的行为。

例如:

printf("%f", 24)

是未定义的行为。 在任何地方都没有从intfloat的转换,因为 arguments 按原样传递(在提升之后),并且在printf内部 function 错误地将其第一个参数视为float printf不知道也无法知道参数的真实类型是int

Variadic arguments 进行了一些自己的促销活动。 对您的问题感兴趣的unsigned char被提升为intunsigned int (我不确定 tbo)。 因此,可变参数实际上无法为unsigned char类型。 所以hhu虽然确实是unsigned char的说明符,但它实际上会期望一个unsigned int ( int ),这就是你传递给它的内容。

所以 afaik 代码是安全的,因为由一元减号和传递可变参数 arguments 引起的两个 integer 促销活动。 不过,我不是 100% 确定。 Integer 促销活动诡异而复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM