の場合、「 L 」が付加されていないためlong double x = 8.99999999999999999
、値は として格納されます。変数をfloat 型としてdouble
既に宣言しているのに、C コンパイラが型を推論できないのはなぜですか?x
long double
5 に答える
C標準標準では、型推論を行わないように明示的に指定されているため、コンパイラは型推論を行いません。
浮動定数に関するセクション6.4.4.2は次のように述べています。
固定されていない浮動定数のタイプはdoubleです。文字fまたはFが接尾辞として付いている場合、タイプはfloatです。文字lまたはLが接尾辞として付いている場合、タイプはlongdoubleです。
なぜ規格はそう言うのですか?コンパイラを単純化するためか、それを行う必要はありません(正直なところ、私にはわかりません)。
1970 年代初頭、C 言語が最初に開発されたとき、コンパイラを実行するコンピュータはメモリが少なく低速でした。このため、コンパイルが高速になるように、コンパイラーが単純になるように言語を設計する必要がありました。単純なコンパイラーは、プログラマーがすべてを伝える必要があります。これは、コンパイラーが推測する必要があるたびに、CPU とメモリーを使用するためです。
もう 1 つの理由は、C を開発して使用している人々が最初に C を使用してオペレーティング システムを作成し、賢くしようとしない言語を望んでいたことです。オペレーティング システムを書くことは、コンパイラが何をするかしないかを推測しなくても十分にトリッキーです。彼らは何が起こるかを非常に正確に制御する必要があり、その意味で、より単純な言語はオペレーティング システムの作成者にとって大きな利点となる可能性があります。
これらのことにより、C は、後の数十年に設計され、アプリケーション プログラミングを目的とした高水準言語が現在備えている多くの機能を持たないことになりました。オブジェクト指向、型推論、ガベージ コレクション、例外、スレッドのサポートはありません。
将来、C がそのようなものを持つように変更される可能性があります (実際、最新の C 標準には現在ネイティブ スレッドがありますが、それらはオプションであると思います)。言語。文字通り何千もの興味深い言語から選択できます。
C は型安全ではないため、C コンパイラは型推論を行いません。簡単に物事を意のままに void にキャストしたり、void ポインターにキャストしたり、再び元に戻すことができます。ルールに反するものではありません。これは、少なくとも、C の型推論は概算にすぎず、せいぜい、型の何が問題なのかについての手がかりをコンパイラに与えることを意味します。
C が型推論を行わない理由について: C の型は、論理関係を強制したり、言語で真実をエンコードしたりすることを意図していません。あるレベルでは、健全な型システムを持つ言語 (Haskell、OCaml、SML、Coq など...) は、型が何かを伝えることを意図しています: 型からプログラムについて書き留めることができる定理があります。(この興味深い例については、Philip Wadler の "Theorem's for Free!" の作品を参照してください!)
では、なぜC は型を使用するのでしょうか。その理由は純粋に、メモリに格納されているデータをどのように編成するかをコンパイラが (あるレベルで) 知る必要があるためです。論理的な一貫性の代わりに、C の型は、物事がどのように配置されているか、構造内のどこにこの int を配置する必要があるかなどを伝えるための肉です...
代わりに、C には、タイプ セーフな言語でより標準的な機能をエミュレートするためのイディオムが多数あります。たとえば、void ポインタは通常、パラメトリック ポリモーフィズムを表すために使用されます。(したがって、たとえば、任意のデータ型へのポインターを含むことができるリストを持つことができます。) 実際、C では、さまざまなデータ型を指すリストをエンコードできます。従来の関数型言語では、リストの帰納型はすべての要素が同じ型である必要がありますが、C では交差型と行を簡単にエンコードできます (たとえば、C では、リスト要素に識別子をタグ付けすることでこれが行われます)。
Cには、型とメモリに安全な方言があります。例としてCycloneを参照してください。いくつかの場所では、C 言語の優れた点の多くを提供しながら、ポリモーフィズムがvoid ポインターなどの発生を置き換えます。
long double の場合 x = 3.0. 値 3.0 は double として格納されます。
違います!それは 3.0 を として保存しlong double
ます。
他の人が標準的な状態を述べているようにthat unless suffixed, a floating point constant is a double
。それでは、計算の複雑さからその背後にある理論的根拠を見てみましょう。スタンダードはまた、とlong double>=double
のシステムを考えてみると述べた。サフィックスのない特定の例では、コンパイラは精度浮動小数点数を計算し、残りの8バイトをゼロにする必要があります。しかし、あなたが示唆するように型推論を行う場合、浮動小数点数を生成するために計算を行う必要があります。sizeof(double)=8
sizeof(long double)=16
64-bit
128-bit
また、浮動小数点数をバイナリ表現に変換するのは簡単な作業ではないため、コンパイラは可能な限りケチをつけようとします。特にこの例では、適切な精度でに絞り込むことができるため、にアップグレード8.99999999999999999
する必要はありません。long double
double