格式说明符是否执行隐式类型转换?

Do format specifiers perform implicit type conversion?

提问人:Tushar K. Sengar 提问时间:1/12/2023 最后编辑:John BollingerTushar K. Sengar 更新时间:1/13/2023 访问量:115

问:

#include <stdio.h>

int main(void) {
    int x = 5;
    int y = &x;

    printf("Signed Value of Y: %d \n", y);
    printf("Unsigned Value of Y: %u", y);

    return 0;
}

由于 yint 类型,因此 using 给出了一个可能带符号的输出,而给出了一个无符号的输出。但是 yint 类型,那么为什么给出无符号输出呢?是否有隐式类型转换?%d%u%u

c 隐式转换 格式说明符

评论

2赞 LHLaurini 1/12/2023
简单地说:不。您应该确保类型匹配。
1赞 phuclv 1/12/2023
否,使用错误的格式说明符只会调用未定义的行为。 对传递的值的类型一无所知,并且必须相信格式说明符所说的内容printf
5赞 Eugene Sh. 1/12/2023
格式说明符根本不执行转换。他们告诉如何在内部解释价值。printf
0赞 0___________ 1/12/2023
是的,但与可变参数函数处理参数的方式有关,而不是与格式说明符有关。例如,如果你传递,它将被转换为 、 等charintfloatdouble
1赞 Eric Postpischil 1/12/2023
@EugeneSh.: Re “Should be clear from the context”:你不能指望那些因为不了解事物而提出问题的人从上下文中了解事物。

答:

1赞 John Bollinger 1/13/2023 #1

是否有隐式类型转换?

算是吧。像这样的函数接受可变数量的参数,它不会自动知道它在任何调用中实际收到的变量参数的数量,或者它们的类型。转换规范(如 和 )共同告知要预期的变量参数数,并分别告知每个参数要预期的类型。 将尝试根据这些规范来解释参数列表。printf%d%uprintf()printfprintf()

C 语言规范明确拒绝说明当 printf 参数的类型与随附的格式字符串中的转换规范不对应时会发生什么情况。然而,在实践中,某些数据类型的对具有足够相似的表示形式,以至于试图将一种类型的数据解释为另一种类型,可能会(但不能保证)给出从一种类型到另一种类型的隐式转换的外观。相应的有符号和无符号整数类型通常是此类对。printf()

你不应该依赖这种明显的转变,实际发生。相反,应将参数类型与转换规范正确匹配。通过选择不同的转换规范或对参数执行适当的显式类型转换(类型转换)来纠正不匹配。

2赞 Eric Postpischil 1/13/2023 #2

实际上,呼叫是两个独立的东西:printf

  • 所有参数都已准备好发送到函数。
  • 该函数解释格式字符串及其其他参数。

在任何函数调用中,参数都是根据涉及参数类型和函数声明的规则准备的。它们不依赖于参数的值,包括作为参数传递的任何字符串的内容,也是如此。printf

在函数调用中,规则主要是(省略一些细节):

  • 如果参数对应于声明的参数类型,则将其转换为该类型。
  • 否则(如果参数对应于函数声明的一部分,或者声明了被调用的函数而未指定参数类型),则应用某些默认升级。对于整数,这些是整数提升,它们在很大程度上(省略了一些细节)将类型转换为 。对于浮点,则提升为 。...intintfloatdouble

printf声明为 ,因此除格式字符串之外的所有参数都对应于 。int printf(const char * restrict format, ...);...

在内部,函数检查其格式字符串并尝试执行格式字符串中给出的指令。例如,如果一个指令是 ,则需要一个参数,并从它期望传递参数的位置获取位。然后,它将这些位解释为 ,根据指令构造一个字符串,并将该字符串写入标准输出。printf%gprintfdoubledoubledouble

对于 or 指令,分别需要 or 参数。无论哪种情况,它都会从它期望传递 or 参数的位置获取位。在我所知道的所有 C 实现中,an 和 an 参数都在同一个地方传递。因此,如果你传递一个参数,但使用 ,将获得 an 的位,但会将它们视为 an 的位。尚未执行实际转换; 只是以不同的方式解释这些位。%d%uprintfintunsigned intintunsigned intintunsigned intint%uprintfintunsigned intprintf

C 标准没有定义执行此操作时的行为,如果 C 实现在执行此操作时崩溃或以不同的方式处理位,则该 C 实现将符合该标准。你应该避免它。

3赞 Harith 1/13/2023 #3

“回复:但是 y 是 int 类型,那么为什么 %u 给出无符号输出?”


从 C11 出发:

如果转换规范无效,则行为为 定义。如果任何参数不是 相应的转换规范,行为未定义。

哪里

undefined — 不正确行为的行为,其中 标准不施加任何要求。任何事情都是允许的 发生,从无到有,到警告消息到程序终止,再到 CPU崩溃,发射核导弹(假设你有 安装了正确的硬件选项)。

— 专家 C 编程。