2009-08-13 20 views
2

私はクラス非静的メンバ関数を持っていますが、それは可変引数を持っています。私はVisual Studio 2005で64ビットランタイムで64ビットWindowsでコンパイルしています。x64 va_list in Visual Studio 2005

void Class::Foo(void* ptr,...) 
{ 
    va_list args; 
    va_start(args,ptr); 
    float f=va_arg(args,float); 
    va_end(args) 
} 

私は浮動小数点数を期待していますが、浮動小数点数を関数に渡します。しかし、私がデバッグするとき - 私は渡されたフロートを取得しません。実際には、それは64ビットの倍数として関数によって受け取られています!私はこれをしなければならない。

double d=va_arg(args,double); 
float f=(float)d; 

今、私はWin64のは、それがこれを行う際に、va_listのは常にスタック上にすべきではないレジスタにパラメータを渡すのが好き、と山車をキャスト知っていますか?

most referencesによると、渡されたパラメータでいっぱいになったきれいなスタックが必要です。

私の質問は、この正しい動作、またはバグですか?それがバグであれば、それは私のバグですか、マイクロソフトのですか?

私はWIN64と_M_AMD64を定義しており、WIN32は未定義です。

答えて

1

ここではC++標準はありませんが、この点についてはC標準に準拠しています。 と呼ばれる関数を示す式は プロトタイプを含まない、引数が 暗黙的の種類に、 割り当てによってかのように、変換されたタイプを持っている場合はC99、6.5.2.2p7は

を語りますそれぞれのパラメータの タイプを の非修飾バージョンの タイプとすると、対応するパラメータは です。 関数プロトタイプ宣言子の省略記号は、 最後に宣言されたパラメータの後で、 引数型の変換を停止させます。 デフォルト引数の昇格は、末尾の引数に対して実行される です。

フロート引数の場合、「デフォルト引数のプロモーション」が実行されます。 と呼ばれる機能を表す式は、プロトタイプ、 キャンペーン各 引数で実行され、整数、およびタイプ を有する引数を含む ないタイプを持っている場合、これらは

としてP6で定義されていますfloatはdoubleに昇格します。これらの はデフォルトの引数 プロモーションと呼ばれます。 [...]

したがって、すべての浮動小数点は、楕円に渡されるときにdoubleに変換されます。 VSは明らかにこの点に準拠しており、コードにはバグがあります。をva_argに使用しないでください。

+0

これは正しいと思います。 C++標準には「デフォルトの引数のプロモーション」については何もありませんが、Cの標準が適用されるとは思えません。私が理解しているように、あなたが引用したテキストによれば、可変引数関数に渡される引数はプロトタイプ化されていないため(変数が変わったときに型のプロトタイプ化ができないため)、常に最大の関連型intまたはdouble。奇妙な振る舞いだと思いますが、明らかにこれがルールです。 – Roderick