web-dev-qa-db-ja.com

C:typedef構造体内の関数ポインタ

リンクリストをCで作成しようとしていますが、C++スタイルのクラスにうまくパックしようとしています。ただし、Cで関数ポインタを使用すると問題が発生します。

typedef struct linkedList {
    int count;
    struct msgNode *front;
    struct msgNode *back;
    void (*addMSG)(unsigned char *, int, struct linkedList *);
} msgList;

void addMSG(unsigned char *data, int size, struct linkedList *self);

理想的には、リストを作成してから、構造内で「メソッド」(関数)を呼び出すだけで、C++で見られる動作をシミュレートできるようにしたいと思います。

現在、addMSGを呼び出すとセグメンテーション違反が発生します。これは、もちろん、addMSGが関数を指していないためです。ただし、リンクリストを使用するたびにポイントする関数を指定する必要はありません。関数を暗黙的に指す必要なしに関数ポインターを持つ良い方法はありますか、それとも暗黙的に関数を指す必要がありますか?

これは、ここに示されている部分的な実装にすぎません。最後に、この構造体は必要なすべての機能を備えています。これは、この質問を短く、要点を絞るためです。

7
Edwin

メンバーに関数を割り当てる必要があります。また、別の名前を付けることをお勧めします。

typedef void (*addMSGFunc)(unsigned char *, int, struct linkedList *);

typedef struct linkedList {
    int count;
    struct msgNode *front;
    struct msgNode *back;
    addMSGFunc addMSG;
} msgList;

void addMSGImpl(unsigned char *data, int size, struct linkedList *self)
{
    ...
}

そして、msgListを作成した後:

msgList myList;
myList.addMSG = addMSGImpl;
21
Asaf

構造体の宣言にデフォルト値を追加することはできませんが、できることは次のとおりです。

  • linkedListインスタンスを初期化する関数を作成します-Cスタイルのライブラリでそれを見たことがあると思います
  • デフォルトのリストアイテムを作成し、それを使用して新しいエンティティを作成します。

お気に入り:

void addMSG(unsigned char *data, int size, struct linkedList *self);

struct linkedList {
    int count;
    struct msgNode *front;
    struct msgNode *back;
    void (*addMSG)(unsigned char *, int, struct linkedList *);
} DefaultList = {0, NULL, NULL, addMSG};
2

実際に使用しない限り、初期化されていない関数ポインタを問題なく使用できます。 doを使用して関数を呼び出す場合は、明らかに関数を割り当てる必要があります。 Cは、使用する関数を推測できません。

関数が必要な場合と不要な場合があるリンクリスト構造がある場合は、リストを作成するときにNULLを割り当て、リストの実装で関数が必要ない場合にのみ関数を呼び出すようにします。 NULL

常に同じ関数を指している場合は、コンストラクター関数で割り当てを行うだけです。

1
Crowman