为什么C没有正确实现隐式转换?

时间:2015-08-29 06:12:28

标签: c++ c implicit-conversion

以下代码打印99其中' c'被隐式转换为99。

printf("%d", 'c');

但以下代码打印0.000000:

printf("%f", 23);

为什么在第二种情况下整数23没有像第一种情况那样转换成23.00000?这是否反映了C中隐式转换的执行不佳?提前谢谢。

编辑:如果没有可能从int到float的提升作为答案之一,那么为什么在我们编写时会有一个int浮动的提升

float x = 23;

为什么会这样?

2 个答案:

答案 0 :(得分:12)

在C中,'c' int。没有进行转换。

即使它是char(就像在C ++中一样),char是一个整数类型,并且在printf等可变函数的参数列表中,所有可变参数都经过算术推广,会自动将char扩展为int,或float扩展为double - 但不会int扩展为{{1} }}

答案 1 :(得分:9)

printf是一个可变函数,这意味着它的参数(除第一个之外)在被访问时实际上是无类型的。这排除了printf的参数列表中的任何类型的智能类型转换(尽管有某些default conversions发生,盲目地且不管格式说明符。)

在第一个示例中,'c'已经是int。但是在float的情况下,它没有执行将int转换为float所需的转换,因为编译器不知道它应该,或者更准确地说,根据规范,那里无所事事,但相信格式说明符是关于类型的真相来源。它认为数据已经是浮点数,因为格式说明符%f正在告诉它,并且它无法看到传入的23的类型。

这使得开发人员很容易意外地导致崩溃 - 开发人员必须确保格式说明符(例如%d)与自己提供的数据相匹配。例如,将“%s”说明符与int输入混合会导致运行时崩溃,因为编译器只会“相信”格式说明符没有错误。更糟糕的是,尝试完全省略数据... printf("%f %f %f")将导致它查找甚至不存在的参数,这些参数将崩溃。遗憾的是编译器必须接受并构建这个崩溃的代码。

如果您想更密切地看到这个难题,请va_list / va_start / va_stopprintf使用。了解这种机制允许我们遍历发送到printf的数据,但是,类型信息丢失了。它是无类型的二进制数据,并且要使用它,它使用格式说明符%f来实现浮点数就在那里。然后它将二进制数据解释为float并在显示之前将其写入字符串。

另一个看待它的角度是编译器在其类型系统中忽略了%f之类的字符串内容... %f已编译但在运行该函数时仅在运行时应用。但是在运行时,所有类型信息都会丢失--C有一个类型系统,但它只是编译时间。基本上,像%f和C类型系统这样的字符串数据是完全没有通信的外来概念。所以试着想象你的程序没有像%f这样的字符串数据。编译器如何知道运行编译时int-> float转换?

同样,这仅适用于可变函数,而不适用于常规函数调用。普通函数调用表现出类似于大多数现代语言的类型处理。另一方面,变量函数对于C来说是唯一的。与void *指针类似,它们应该被认为是危险的并且要小心使用。

编辑: float x = 23;导致促销,因为该语言具有功能类型系统(尽管类型仅在编译时已知)。类型系统在可变参数函数内部不起作用,即printf的输入。