2

クラスの非静的メンバー関数があり、可変引数があります。64 ビット Windows で、64 ビット ランタイムを使用して Visual Studio 2005 でコンパイルしています。

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

float を期待しています。float を関数に渡します。しかし、デバッグすると、渡したフロートが得られません。実際、これは関数によって 64 ビット double として受信されています! 私はこれをしなければなりません:

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

これで、Win64 はレジスタでパラメータを渡すのが好きで、これを行うときにフロートをキャストすることがわかっています。

ほとんどの参照によると、渡されたパラメーターでいっぱいのクリーンなスタックが必要です。

私の質問は次のとおりです。これは正しい動作ですか、それともバグですか? また、それがバグである場合、それは私のバグですか、それとも Microsoft のバグですか?

WIN64 と _M_AMD64 を定義していますが、WIN32 は未定義です。

4

2 に答える 2

1

VC++x64のバグのようです。

修正:va_arg関数がVisual C++2005アプリケーションで誤った値を返す

于 2009-08-14T20:55:31.723 に答える
1

ここには C++ 標準はありませんが、この件に関しては C 標準に準拠しています。C99、6.5.2.2p7 は言う

呼び出された関数を示す式がプロトタイプを含まない型を持っている場合、引数は対応するパラメーターの型に代入のように暗黙的に変換され、各パラメーターの型は宣言された型の非修飾バージョンになります。タイプ。関数プロトタイプ宣言子の省略記号表記により、最後に宣言されたパラメーターの後で引数の型変換が停止します。デフォルトの引数昇格は、末尾の引数に対して実行されます。

したがって、float 引数の場合、「デフォルトの引数プロモーション」が実行されます。これらはp6で次のように定義されています

呼び出された関数を示す式の型がプロトタイプを含まない場合、各引数に対して整数昇格が実行され、float 型の引数は double に昇格されます。これらは、デフォルト引数プロモーションと呼ばれます。[...]

したがって、すべての float は、楕円に渡されるときに double に変換されます。VSはこの点で明らかに準拠しており、バグはあなたのコードにありfloatva_arg.

于 2009-08-13T12:55:32.117 に答える