dポイントプレゼントキャンペーン実施中!

またまた float がらみでつまずています。

以下のようなソース(2つのファイルに分割されています)を実行すると、
f = 2.000000
と表示されました。

test1.c で、func() のプロトタイプを書いてないのが諸悪の根源だとは思うのですが(警告もでています)プロトタイプの役割は、

・引数の型の不整合がないようにする
・必要に応じて、仮引数と実引数の型変換を発生させる

だと思います。

このソースでは(たまたまですが)引数の型もあっているので、正常に実行できそうな気がするのですが、なぜ、結果がおかしくなってしまうのでしょうか。
確かに、プロトタイプがないのは好ましくはないですが。

test1.c に、int func(float f); を追加したときには、確かに f = 0.010000 と表示されます。
また、f と func() の引数を double にしたときには、プロトタイプがなくても、正常に実行されます。

----- test1.c -------------

int main()
{
float f = 0.01;

func(f);
return 0;
}

----- test2.c -------------

#include <stdio.h>

int func(float f)
{
printf("f = %f", f);
return 0;
}

----- ここまで ------------

A 回答 (4件)

既に回答にあるように、プロトタイプがない場合、float は、double に「格上げ」されてから、関数に渡されます。



これは、大昔のC……その頃まだ、プロトタイプという概念もなかった頃(先行宣言はあった)、引数においては、
・int より小さい整数(char も)は、int に
・float は、double に
それぞれ格上げされてから関数に渡されると、そう決めた(知る人ぞ知る『K&R』の時代にまでさかのぼる)というのが前段にあるわけです。
※なぜ、わざわざそう決めたのかは、わかりませんでした。

時代が下って、プロトタイプが存在するようになった現在、プロトタイプで決められた引数の型に対して、「代入するのと同じように」型変換(同じ型なら、もちろん、変換無し)されて受け渡されるようになりました。
※ただし、printf() のような可変引数の部分は、「省略された引数リスト」ということで、プロトタイプの場合と同じ「格上げ」が発生する。

そういうわけで、プロトタイプなしで関数を呼び出したときに、引数が float だと、格上げの影響でdouble に変換されてから関数に渡されました。
受けとるほうの関数は、float が来たと思っているので、良くないことが起こりましたとそういうわけです。

引数が double だった場合には、格上げなど無しでそのまま渡されるので、(たまたま引数があっていれば)正常に実行されたというわけです。
    • good
    • 0
この回答へのお礼

ありがとうございました。
「格上げ」で、いろいろ検索してしまいました。

そいうえば、printf() の場合、float は、double に変換して渡されるというのは聞いたことがありました。
同じような話だったのですね。

ありがとうございました。

お礼日時:2010/11/12 17:29

ほんと~に初期のころは, 関数に引数として渡す時だけでなく, 式の中で使うときは常に


・int より小さい整数型 (char と short) は int にする
・float は double にする
という変換をしてましたよね>#3.
「float で計算させるといったん double に変換してから計算するので遅くなる」という話を聞いたものです.
    • good
    • 0
この回答へのお礼

ありがとうございました。

そういえば、char は int にして計算されるというのは、聞いたことがありました。

float が一度 double に変換されるのも、聞いたことあるような。

それぞれ聞いたことはあるのに、なにか、頭の中でつながってなかった気がします。

お礼日時:2010/11/12 17:32

プロトタイプがない場合、floatはdoubleに変換されて渡されるのが規格です。

    • good
    • 0
この回答へのお礼

ありがとうございました。

何かおかしくなっていると思ったのは、double に変換されていたからなのですね。
int がおかしくなるとなんとか見当も付くのですが、浮動小数点でおかしくなると、お手上げでした。

お礼日時:2010/11/12 17:33

>・引数の型の不整合がないようにする


不整合をチェックして一致しなければエラーにする。

>・必要に応じて、仮引数と実引数の型変換を発生させる
こんな事はしません。

>f と func() の引数を double にしたときには、プロトタイプがなくても、正常に実行されます。
偶然でしょうね。

関数プロトタイプがなくて、偶然の結果を信じる人が多くて、プロトタイプ書かなくてもいいと
言い張る人は多いです。
ま、宗教のようなものですから相手にしないことです。

この回答への補足

>・必要に応じて、仮引数と実引数の型変換を発生させる

たとえば、

void func(int i);
というプロトタイプに対して、
func(12.3);
という呼び出しは、double -> int への型変換を発生させると思うのですが。

この場合、プロトタイプがないとコンパイルではエラーがなく(警告は出ますが)実行時には見事に失敗します。

補足日時:2010/11/12 15:28
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!