2011-10-12 26 views
9

GCCは、次のコードは、値を変更することが暗黙の変換が含まれていることを私に警告:GCCがこの暗黙の変換に対して警告するのはなぜですか?

float square = 100; 

GCCによって与えられる警告:

#include <stdlib.h> 
float square = rand(); 

しかし、以下に警告を生じません次のされています

tests/ChemTests.cpp:17:23: error: conversion to ‘float’ from ‘int’ may alter its value 

前者は警告を与えるだろう、なぜrand()がpであるので、私は、理解していません明示的に宣言し、100整数リテラルと同様にintを返します。

は、なぜ最初の行は、両方がintからfloatへの暗黙的な変換を持っているにもかかわらず、コンパイラの警告ではなく、秒を与えるのでしょうか?

+0

私が '-Wconversion'オプションを使わない限り、警告が出ないことがわかりました。 –

答えて

14

GCCは、キャストによって精度が低下する可能性がある場合に、この警告を表示します。 (換言すれば、値は「変更されている」)

最初のケースでは、rand()intを返します。 intに格納できる値はすべてfloatであるわけではないため、この警告が出力されます。

精度が低下することなく、100を安全にキャストすることができます(float)。

+0

これは 'float f = 123456789'がエラーを起こすことを意味しますか? –

+0

エラーは発生しませんが、警告が表示されます。私はこの瞬間に私の前にGCCを持っていませんが、Visual Studioでテストしたところ、警告が表示されます: '警告C4305:'初期化 ':' int 'から' float 'への切り捨て – Mysticial

5

Mysticialが書いたものに何かを追加するには(つまり、正しいです):Cの実装は32 bits IEEE 754 single precision binary floating-pointと32ビットですintあるfloatを使用しています。 「あなたの」intには、31ビットの数字と1ビットの符号を付けることができます。あなたのフロートでは、mantissaは24ビットで、1ビットの符号があります。明らかに、intは24ビット以上の符号を表現する必要があり、正確に "自分の" floatに変換することはできません。 (私はあなたの "あなたの"コンパイラ、あなたが使用しているコンパイラを表すために使用します.C標準はfloatまたはintの正確な長さを教えていません)。

rand()は、intという数字を生成できるため、コンパイラは警告を表示する必要があります。 100はコンパイル時に知られている数値リテラルなので、コンパイラはその数値が変換可能かどうかを静的にチェックできます。

intは32ビットで浮動小数点数をサポートしています(floatは浮動小数点数を「サポート」しています)浮動小数点数の表現が難しいあなたは、小数点がどこにあるか)どこかに保存する必要がありますので、「価格」intfloatの両方が同じ長さを持っている場合、あなたが支払う価格は精度がなければならない。)

をあなたが作ったコメントに対応するため、 floatで正確に表すことのできる最大数は0に "連続"しています(つまり、0 ...数はすべて正確に表現可能です)16777215(仮数= 16777215およびexp onent = 0)と16777216(それは1 * 2^24なので、仮数= 1と指数= 24です)。 16777217は正確に表現できません。 16777218はです。

0

intのすべては、floatとして表すことができません。具体的には、intに設定された最上位ビットと最下位ビットとの間のビット数が、で定義されるFLT_MANT_DIG - 1より大きい場合、正確にはfloatとして表すことはできない。 (doubleDBL_MANT_DIG - 1の場合も同じです)rand()という宣言は、floatとして表現できないものも含めて、rand()intを返す可能性があることを意味するため、コンパイラは精度が低下する可能性があることを警告します。

float f= 1<<FLT_MANT_DIG; // yes 
float g= (1<<FLT_MANT_DIG) - 1; // yes 
float h= (1<<FLT_MANT_DIG) + 1; // no 
float i= (1<<(FLT_MANT_DIG + 1)); // yes 

gccが唯一hを初期化するための警告を吐き出す必要があります。

gccがintリテラルを正確に表現することができたときに知っているのに十分にスマートでなければなりません。 RAND_MAX(1<<FLT_MANT_DIG) - 1以下である場合に

ところで、あなたが安全に、コンパイラがあなたに文句を言う場合でも、floatrand()を割り当てることができます。

関連する問題