1

後で私が持っている関数に割り当てることができる関数ポインタを作成することが可能かどうか尋ねたいと思います.

typedef struct 
{
    char *name ;
    void (*func0)(void) ;
}option;

int test(int i)
{
    return i;
}

オプション パラメータまたは関数のいずれかをキャストして、後でオプション パラメータを呼び出して関数として使用できるようにする方法を教えてください。
私は試した:

op.func0= test ;
または:
(int)op.func0= test ;
失敗しました。

4

3 に答える 3

5

Cでは、関数を次のように保存できます

void * (*func)();

func = test;

ただし、それを呼び出すときは、適切な型にキャストする必要があります

int ret = ((int (*)())func)(a);

これは、任意のターゲット アーキテクチャでは安全とは見なされません。x86 では動作するはずですが、他のアーキテクチャではこれらのトリックを避ける必要があります。

編集:

タイプキャスト警告を回避したい場合は、次のように割り当てを行います

func = (void * (*)())test;

この型キャストを使用すると、次のようにコンパイルされますgcc -pedantic

于 2013-08-13T12:32:25.200 に答える
1

関数を別の関数ポインター型にキャストしても問題ありません。使用する前に必ずキャストし直す必要があります。次に例を示します。

#include <stdio.h>

typedef struct 
{
    char *name ;
    void (*func0)(void) ;
} option;

int test(int i)
{
    return i;
}

int main(int argc,char **argv)
{
    option a;
    int i;

    a.func0 = (void(*)(void))test;
    i = ((int(*)(int))a.func0)(5);
    printf("%d\n",i);
    return 0;
}

を出力します5

于 2013-08-13T12:45:30.423 に答える
0

コール シグネチャに限定的な (つまり、実際的な) 制限がある場合は、異なるシグネチャのポインタの結合を使用できる可能性があります。

typedef ユニオン call_sigs_union
{
    ボイド *void_void; // 純粋な void ポインター
    int (*int_sig_void)(void); // 引数なしの整数を返す
    int (*int_sig_int)(int); // 単一の int 引数を持つ整数を返します
  . . .
} sigs_t;

これの利点は、すべてをキャストする場合よりも、何か間違ったことをしている場合に、コンパイラからの警告が改善されることです。

警告: これは多くのアーキテクチャで保証されているわけではありません。理論的には、さまざまな戻り値の型、およびおそらく署名が異なるポインター型を持つ可能性があるためです。私はいくつかのシステムについて読んだことがありますが、これが実際に発生するシステムについては聞いたことがありません。Intel X86、Itanimum、Sun SPARC、および IBM RISC は、私が使用したことのある適切に動作するシステムの一部です。私が ARM アーキテクチャについて読んだことに注意すると、これらは問題になると思います。

通常、奇妙な動作は専用プロセッサに限定されます。これが壊れるシステムで誰かが私の記憶をリフレッシュできますか?

于 2013-08-13T12:54:23.210 に答える