ただし、すべてが関数テーブルに配置されるときに正しい関数型にキャストされるため、警告は発生しません。
したがって、コンパイラは何の役にも立ちません。C プログラマーはキャストしすぎます。>_<
関数パラメーターが C で渡される方法によってこれが保証されているかどうかは判断できません。sprintf のような可変引数関数を実行するには、パラメーター リストの最後にあるものが何であれ、以前の引数を正しく解決できる必要があります。 ?
技術的には、未定義の動作があります。ただし、プラットフォームが標準の C 呼び出し規則 (Scott の回答を参照)、またはそれらに直接マップするもの (通常、最初の N 個のパラメーターを特定のプロセッサ レジスタのセットにマップすることによって) を使用するように定義されています。
これは可変引数リストでもよく出てきます。たとえば、printf
次のように宣言されています。
int printf(const char* format, ...);
そして、その定義は通常、stdarg
システムを使用して追加の引数を処理します。これは次のようになります。
#include <stdarg.h>
int printf(const char* format, ...)
{
va_list ap;
int result;
va_start(ap, format);
result = vprintf(format, ap);
va_end(ap);
return result;
}
標準の C 呼び出し規則を使用するプラットフォームを使用している場合、そのva_end(ap)
マクロは通常、何も実行しません。この場合、余分な引数を関数に渡すことで回避できます。しかし、一部のプラットフォームではva_end()
、スタックを予測可能な状態 (つまり、 への呼び出し前の場所) に復元するために呼び出しが必要ですva_start
。そのような場合、関数は見つかった方法でスタックを離れることはありません (スタックから十分な引数をポップバックしません)。そのため、呼び出し元の関数は、たとえば、戻り値として偽の値をフェッチすると、終了時にクラッシュする可能性があります。住所。