7

次の行に沿って、関数ポインターの配列に割り当てられる一連の C 関数があります。

typedef int (*func)(int);

int SomeLongName1(int a) {         
  // ...
}                      

// ...

int SomeLongName1000(int a) {         
  // ...
}                      

func f[] = { SomeLongName1, ... , SomeLongName1000 };

これを作成するには多くの作業が必要であり、エラーが発生しやすくなります。たとえば、関数名にタイプミスがある可能性があります。たとえば、有効な関数には名前が付けられているのに、間違った名前が付けられている可能性があります。または、新しい関数が最後に追加された場合、関数ポインターのリストにも明示的に追加するのを忘れる可能性があります。

関数ポインターの配列を明示的に宣言する必要がないように、マクロなどのさまざまなトリックを試しましたが、コードがわかりにくく、マクロのしくみを知る必要がありましたが、一般的には満足していません。

私がやりたいことは次のようなものです:

typedef int (*func)(int);

func f[] = {             
  int SomeLongName1(int a) {         
    // ...
  }                      
  // ...                   
  int SomeLongName1000(int a) {         
    // ...
  }                      
};                       

このようにして、配列は自動的に作成され、最後に null ポインターを置く方法があれば、関数ポインターがいくつあるかを判断できます。

ただし、上記は有効な C ではなく、これを達成する方法は何もありません。コンパイラ固有のもの (GCC 拡張機能など) であれば問題ありません。

すべての関数はコンパイル時に静的に認識されるため、関数ポインター配列の実行時の初期化を行う必要がないようにしたいと思います-そのようにする方法を見つけたわけではありません。

この関連する質問How to define an array of functionsは、同じ質問をしているようですが、論理的な結論には至りません。具体的には、時間を節約し、エラーを回避するために、既に入力したものを再入力する必要はありません。

4

4 に答える 4

4

配列内の関数の順序を気にせず、GCC 拡張機能を使用したい場合は、一連の初期化 (コンストラクタ) 関数を使用して目的を達成できます。これは、非常に多くの追加関数が定義されているため明らかに理想的ではありませんが、検討できる 1 つのアプローチであることは確かです。実行時に配列を構築します。

関数を定義してappend、単一の関数を配列に追加します (必要に応じて再割り当てします)。次に、コードは基本的に

#define ARRAYFUNC(name) int name(int); \
    void __attribute__((constructor)) __init_##name(void) { append(func); } \
    int name(int a)

ARRAYFUNC(func1) {
    ...
}

ARRAYFUNC(func2) {
    ...
}
于 2013-09-13T21:13:49.570 に答える
3

これには C プリプロセッサ ( X-Macros ) を使用できます。

#include <stdio.h>

// define a list of function names and bodies
#define FUNCS \
  FUNC(add, { return a+b; }) \
  FUNC(mul, { return a*b; }) \
  FUNC(div, { return a/b; })

// let the preprocessor make up the actual function implementations
#define FUNC(name, body) int name(int a, int b) body
FUNCS
#undef FUNC

typedef int (*func)(int, int);

// let the preprocessor populate the array of function pointers
func f[] = {
#define FUNC(name, body) name, 
FUNCS
#undef FUNC
};

// use it:
int main () {
    int a = 2, b = 3, i = 0;
    for (; i < sizeof(f)/sizeof(*f); i++) {
        printf("%d\n", f[i](a,b));
    }
    return 0;
}

出力は次のとおりです。

$ gcc test.c && ./a.out
5
6
0
于 2013-09-13T20:47:30.497 に答える
2

このような状況を解決するために私が使用するのは (もちろん、それを回避できない場合のみ)、前処理を使用することです。C プリプロセッサから利用できるものではなく、実用的な構文で必要な機能を提供していませんが、m4.

を使用m4すると、コードは次のようになります。

define(`functionList', `, 0')
define(`functionArrayMember', `define(`functionList', `$1, 'FunctionList)$1')
define(`buildFunctionArray', `{ functionList }')

int functionArrayMember(SomeLongName1)(int a) {
    return a+1;
}
//...
int functionArrayMember(SomeLongName1000)(int a) {
    return a+1;
}

func f[] = buildFunctionArray();

との正しいm4定義を提供するだけで、必要な機能が得られます。functionArrayMember()buildFunctionArray()

于 2013-09-13T19:42:41.160 に答える