2017-05-01 11 views
-1

私のプログラムでは、常に引数よりも近い最も近い整数値を取得する必要があります。そのため私はC ceil()機能を使用しています。 問題は常に私が期待していない数値を返すことです。C ceil()関数は奇妙な数値を返します

など。以前の私のプログラムで

double num = 1/25.0; // num is correctly 0.04(some 0s)1 
ceil(num);    // ceil returns 1018 

私はので、私は多分それはそれとは何かを持っていると思ったし、私はそれをコメントアウトが、それは助けていない、srand(time(NULL))を呼んでいます。

ceil(0.040000001)のような関数を呼び出すと、1018も返されます。 ドキュメントから引数を取って関数を呼び出すときでさえ、この奇妙な動作をします。

プログラム例

//#include <stdio.h> 
//#include <stdlib.h> 

int main() { 

    //double var = 1/25.0; 
    double num1 = ceil(1.6); // returns 1023 

    return 0; 
} 
+7

私は[mcve] – tkausl

+2

が必要です*どのように戻り値をチェックしますか? – UnholySheep

+6

math.hが含まれていますか?正しいプロトタイプがなければ、Cは 'int ceil(int);と仮定します。 –

答えて

3

としてはdoubleを返しceil、コメントで指摘していますが、関数のプロトタイプを指定しない場合、コンパイラは、関数がintを返し、種類ということを前提としなければなりませんの引数(default argument promotionsの適用後)は、関数のパラメータの型と同じです。実際の関数が呼び出されると、パラメータの型が間違っているため(ceildoubleを返しますが、intを渡します)、動作は定義されていません。

現代の多くのシステムでは、浮動小数点引数と整数値引数は同じレジスタでも渡されません。この場合、ceildouble引数を探していて、浮動小数点引数のためにレジスタ内に何らかのゴミがあっただけです。 intの戻り値を期待している呼び出し側は、整数リターンのためにレジスタ内に何らかのガベージが発生した場合にのみ検出しました。

コンパイラは、デフォルトでは非プロトタイプ関数を呼び出すことについて警告する必要があります。警告を確認すると、そのような問題は回避されます。

+2

x64などのレジスタが豊富なアーキテクチャでは、浮動小数点数と整数が異なるレジスタに渡される可能性が高いので、' ceil'は間違っています浮動小数点レジスタに何が起こったのかを取得し、戻り値が間違っている場所を探していて、整数レジスタに何らかのガーベッジがあった場合は取得します。したがって、返される値と渡された値との間には必ずしも相関関係はありません。 – trentcl

+0

@trentcl答えはコミュニティウィキですので、コメントは必要ありません。あなたは答えを編集し改善することができます。 – chux

関連する問題