如果是long double x = 8.99999999999999999
,则值将存储为double
,因为未附加“L”。当我已经将变量x
声明为long double
浮点类型时,为什么C编译器不能进行类型推断?
答案 0 :(得分:4)
编译器不进行类型推断,因为the C standard标准显式指定
。关于浮动常数的第6.4.4.2节说:
未固定的浮动常数具有double类型。如果以字母f或F为后缀,则为 键入float。如果以字母l或L为后缀,则其类型为long double。
为什么标准这样说?也许是因为它简化了编译器,而不是必须这样做(说实话,我不确定)。
答案 1 :(得分:4)
在20世纪70年代早期,当C语言最初开发时,运行编译器的计算机速度很慢,内存很少。因此,有必要设计语言,以便编译器可以很简单,这样编译速度可以很快。一个简单的编译器需要程序员告诉它一切,因为每次编译器需要推导时,它都会使用CPU和内存。
另一个,我认为同样重要的原因是,最初开发和使用C的人正在用它编写一个操作系统,他们想要的语言并不是那么聪明。编写操作系统非常棘手,无需猜测编译器可能做什么或不做什么:他们需要对发生的事情进行非常精确的控制,而在这种意义上,更简单的语言对操作系统编写者来说是一个很大的好处。
由于这些原因,C最终没有很多高级语言在以后几十年设计并且针对应用程序编程的功能。它没有面向对象,没有类型推断,没有垃圾收集,没有例外,也没有线程支持。
将来C可能会被改为拥有这样的东西(事实上,最新的C标准现在有本机线程,但我相信它们是可选的),但总的来说,如果你想要那些东西,你呢想要一种不同的语言。有数千种有趣的语言可供选择。
答案 2 :(得分:3)
C编译器不进行类型推断,因为C 不是类型安全的。你可以很容易地把事情变成无效,无效指针,然后再回来。这不符合规则。这至少意味着对C的任何类型的推断都只是近似的,并且最多你会让编译器为你提供关于你的类型出了什么问题的线索。
至于为什么C不进行类型推断:C中的类型不旨在强制执行逻辑关系,或者用语言编码真值。在某种程度上,具有声音类型系统的语言(Haskell,OCaml,SML,Coq等......)意味着类型告诉你你的东西:有一个定理,你可以写下你的程序来自类型。 (请参阅Philip Wadler的“免费定理!”作为一个有趣的例子!)
为什么 C使用类型?原因很简单,编译器需要知道 - 在某种程度上 - 如何组织存储在内存中的数据。而不是逻辑一致性,C中的类型可以告诉你如何布局,我应该把这个int放在一个结构中等等......
相反,C有许多习惯用于模仿类型安全语言中的更多标准功能。例如,void指针通常用于表示参数多态。 (例如,你可以有一个列表,其中可以包含指向任何数据类型的指针。)事实上,它做了更多的事情,在C中你可以编码指向不同数据类型的列表。在传统的函数式语言中,列表的归纳类型要求所有元素都属于同一类型,您可以在C中轻松编码不合格类型和行(例如,在C中,通过使用标识符标记列表元素来完成)。
是类型和内存 C的安全方言,请参阅Cyclone作为示例,在某些地方,多态 >替换像void指针这样的事情,同时仍然给你很多C语言的细节。
答案 3 :(得分:1)
在长双x = 3.0的情况下。值3.0存储为double。
不正确!这将存储3.0作为long double
。
答案 4 :(得分:1)
正如其他人所说的标准状态that unless suffixed, a floating point constant is a double
。现在,让我们从计算复杂性中看出它背后的基本原理。标准还注意到long double>=double
现在考虑一个sizeof(double)=8
和sizeof(long double)=16
的系统。现在,在您的特定示例中,没有后缀,编译器必须只计算64-bit
精度浮点数,并将剩余的8个字节清零。但是如果按照你的建议进行类型推断,它现在必须进行计算以产生128-bit
浮点数。
并且converting a floating point number into binary表示并不是一件容易的事,因此编译器尽可能地吝啬。特别是在此示例中,无需将8.99999999999999999
升级到long double
,因为它可以合理准确地压缩到double
。