3

在 的情况下,由于未附加“ L ” long double x = 8.99999999999999999,因此该值被存储。double当我已经将变量声明xlong double浮点类型时,为什么 C 编译器不能进行类型推断?

4

5 回答 5

4

编译器不进行类型推断,因为C 标准标准明确规定应该这样做。

关于浮动常量的第 6.4.4.2 节说:

无后缀的浮点常量具有 double 类型。如果以字母 f 或 F 为后缀,则为 float 类型。如果以字母 l 或 L 为后缀,则它的类型为 long double。


为什么标准会这样说?也许是因为它简化了编译器,而不是必须这样做(老实说,我不确定)。

于 2012-04-06T08:50:26.040 回答
4

在 1970 年代初期,当 C 语言首次开发时,运行编译器的计算机速度很慢,内存很少。因此,有必要设计语言,使编译器简单,编译速度快。一个简单的编译器需要程序员告诉它一切,因为每次编译器需要推导时,它都会使用 CPU 和内存。

另一个,我认为同样重要的原因是,开发和使用 C 的人最初是用它编写操作系统,他们想要一种不试图变得聪明的语言。编写操作系统非常棘手,无需猜测编译器可能会或可能不会做什么:他们需要对发生的事情进行非常精确的控制,从这个意义上说,更简单的语言对操作系统编写者来说可能是一个很大的好处。

由于这些原因,C 最终没有许多高级语言在后来的几十年中设计并针对应用程序编程现在拥有的许多特性。它没有面向对象,没有类型推断,没有垃圾收集,没有异常,也不支持线程。

将来 C 可能会被更改为具有这样的东西(事实上,最新的 C 标准现在有本地线程,但我相信它们是可选的),但总的来说,如果你想要这些东西,你想要一个不同的语言。确实有成千上万种有趣的语言可供选择。

于 2012-04-06T09:01:20.207 回答
3

C 编译器不进行类型推断,因为 C不是类型安全的。您可以轻松地将事物随意转换为 void、void 指针,然后再返回。这并不违反规则。这至少意味着,任何类型的 C 类型推断都只是近似的,并且充其量你会让编译器为你提供关于你的类型出了什么问题的线索。

至于为什么 C 不进行类型推断:C 中的类型不是为了强制逻辑关系,或者在语言中编码真理。在某种程度上,具有健全类型系统的语言(Haskell、OCaml、SML、Coq 等)旨在让类型告诉你一些事情:你可以从类型中写下一个关于你的程序的定理。(请参阅 Philip Wadler 的“Theorem's for Free!”这个有趣的例子!)

那么为什么C使用类型呢?原因纯粹是编译器需要知道——在某种程度上——如何组织你的数据,因为它存储在内存中。C 中的类型不是逻辑一致性,而是告诉你事情是如何布局的,我应该把这个 int 放在结构中的什么位置,等等......

相反,C 有许多习惯用法来模拟类型安全语言中的更多标准特性。例如,空指针通常用于表示参数多态性。(例如,你可以有一个列表,它可以包含指向任何数据类型的指针。)事实上,它做了更多的事情,在 C 中你可以对指向不同数据类型的列表进行编码。虽然在传统的函数式语言中,列表的归纳类型要求所有元素都属于同一类型,但您可以在 C 中轻松地对交叉类型和行进行编码(例如,在 C 中,通过使用标识符标记列表元素来完成)。

C有类型内存安全的方言,以Cyclone为例,在某些地方,多态确实取代了诸如 void 指针之类的东西,同时仍然为您提供了 C 语言的许多细节。

于 2012-04-07T18:25:01.617 回答
1

在 long double x = 3.0 的情况下。值 3.0 存储为双精度值。

不对!这会将 3.0 存储为long double.

于 2012-04-06T08:14:11.127 回答
1

正如其他人所说的标准状态that unless suffixed, a floating point constant is a double。现在,让我们从计算复杂性来看其背后的基本原理。标准还指出,long double>=double现在考虑一个系统 wheresizeof(double)=8sizeof(long double)=16。现在在没有后缀的特定示例中,编译器只需计算一个64-bit精度浮点数并将剩余的 8 个字节归零。但是,如果要按照您的建议进行类型推断,则现在必须进行计算以产生128-bit浮点数。

将浮点数转换为二进制表示并非易事,因此编译器会尽可能地小气。特别是在这个例子中,不需要升级8.99999999999999999到,long double因为它可以double以合理的精度压缩成一个。

于 2012-04-06T09:27:15.770 回答