コードの意味は次のとおりです。
- のアドレスを取得します
fptr
。この式の型は、ポインターから関数へのポインター (特定の型) です。
- そのポインター式を「void へのポインターへのポインター」にキャストします。
- そのポインターを逆参照して
fptr
、オブジェクトが type のオブジェクトであるかのようにアクセスしますvoid *
。
- 権利の結果を手順 3 で取得した左辺値に代入します。
残念なことに、この例を POSIX で書いた人は、ステップ 3 が C 言語のエイリアシング規則に違反しているため、未定義の動作を引き起こすため、問題を抱えていました。特に、実際のコンパイラは、意図した使用法を破る方法でこのコードを最適化します。
この例の作成者が達成しようとしていたのは、右辺をポインターから voidへ、ポインターから関数へとキャストすることを回避することでした。これは、C 標準では警告を生成するためにこのキャストが必要であるという主張に基づいていますが、そのような要件を徹底的に検索しましたが、そのような要件は見つかりませんでした。
そのような問題が実際に存在する場合 (警告の要件)、未定義の動作 (POSIX のテキストの悪い例のように) を呼び出さずに警告を黙らせる唯一の方法は、次のようにすることです。
void (*fptr)(); // or whatever function pointer type you want
void *temp = dlsym(handle, "my_function");
memcpy(&fptr, &temp, sizeof fptr);