printf()

问题描述

在这种情况下,

#include <stdio.h>

int main()
{
    unsigned char a = 1;
    printf("%hhu",-a);

    return 0;
}

-a 中的参数 printf 通过一元减运算符的整数提升提升为 int,随后通过默认参数提升提升,最后转换为 unsigned char通过格式说明符。
所以 -a => -(int)a(by ~) => 没有通过函数调用转换 => (unsigned char)-(int)a(by %hhu)。我的想法对吗?

解决方法

您是正确的,aint 中被提升为 -a,并且 printf("%hhu",-a);int 传递给 printf。使用 %hhu 执行的概念转换尚不清楚。

请注意,如果 a 不为零,则 -a 生成的值(在 int 中)不是 unsigned char 值。此外,对于八位 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 参数(参数将根据整数提升而提升,但其值应在打印前转换为 signed charunsigned char);...

首先我们必须解决“signed char unsigned char”这个问题。这是否表示我们可以为 signed char 传递 unsigned char%hhu?我想不是;我认为作者刚刚将 %hhd(旨在转换 signed char)和 %hhu(旨在转换 unsigned char)的语言放在一起。所以我相信其意图是应该为 unsigned char 转换规范传递一个提升的 %hhu

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 是一个可变参数函数。 ... 参数传递的参数类型在函数内部未知。因此,任何可变参数函数都必须依赖其他机制来解释 va_arg 的参数类型。 printf 和 family 使用 const char* format 字符串来“告诉他们”传递了什么样的参数。传递与其格式说明符指定的预期类型不同的类型会导致未定义行为。

例如:

printf("%f",24)

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

可变参数会经历一些自己的提升。您感兴趣的问题 unsigned char 被提升为 intunsigned int(我不确定 tbo)。因此,可变参数实际上无法成为 unsigned char 类型。所以 hhu while 确实是 unsigned char 的说明符,它实际上期望一个 unsigned int (int),这就是您传递给它的内容。

因此,由于一元减号和传递可变参数引起的两个整数提升,因此代码是安全的。不过,我不是 100% 确定。整数促销既奇怪又复杂。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...