以下のソースコードを使用して、「関数の動的呼び出し」を試しています。最初の 2 つの引数のみを受け入れる testing_function でこのコードを正常にテストした後、3 番目の引数を追加し、関数を呼び出すときに「引数を指定しない」ことにしました。これを行うと、3 番目の引数の値が (必ずしも) 0 ではなく、元がわからない「ランダムな」値であることに気付きました。
質問は次のとおりです。
- これらの値はどこから来たのですか?
- さらに、引数はどのように関数に渡されますか?
- 引数を渡さないのは悪い習慣ですか?
- 関数を利用するコードを再コンパイルせずに、関数の引数への追加に備えることができますか? (例: 動的にロードされたライブラリの関数は受け入れられる引数を取得しますが、関数を使用するコードは再コンパイルされません)。
ソースコードの序文は次のとおりです。
Linux を使用して実行し、GCC 4.6.3 でリンカーをコンパイル/呼び出していますが、このコードを使用してもコンパイル/リンクの警告/エラーは表示されません。このコードは「完全に」実行されます。次のように gcc を呼び出します。
gcc -x c -ansi -o (output file) (input file, .c suffix)
ソースコードは次のとおりです。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
/* Function for testing. */
int testing_function(char* something, char* somethingelse, int somethingadditional)
{
int alt_errno = errno;
if ((something != NULL)&&(somethingelse != NULL))
{
errno = 0;
if (fprintf(stdout, "testing_function(\"%s\", \"%s\", %d);\n", something, somethingelse, somethingadditional) <= 0)
{
if (errno != 0)
{
int alt_alt_errno = errno;
perror("fprintf(stdout, \"testing_function(\\\"%%s\\\", \\\"%%s\\\", %%d);\\n\", something, somethingelse, somethingadditional)");
errno = alt_errno;
return alt_alt_errno;
}
else
{
errno = ENOSYS;
perror("fprintf(stdout, \"testing_function(\\\"%%s\\\", \\\"%%s\\\", %%d);\\n\", something, somethingelse, somethingadditional)");
errno = alt_errno;
return ENOSYS;
}
}
else
{
errno = alt_errno;
return 0;
}
}
else
{
errno = ENOSYS;
perror("testing_function(char* something, char* somethingelse, int somethingadditional)");
errno = alt_errno;
return ENOSYS;
}
}
/* Main function. */
int main(int argc, char** argv)
{
int (*function)(char*, char*);
*(void**) (&function) = testing_function;
exit(function("Hello", "world!"));
}