2

私は最近、C の関数ポインターの魔法を発見し、かなり大きな switch ステートメントを関数ポインターの適切な配列に変換しています。簡単な関数呼び出しのために、単純なルックアップ テーブルを使用して関数ポインター配列にマップしたいと考えています。

問題は、オペコードがいたるところにあり、それらの間に大きなギャップがあることです。opcodearray にインデックスを付けるためにスペースを空けるために、0 の巨大な配列は必要ありません。メモリは大きな懸念事項です。

たとえば... 0x0000 はオペコードではありません 0x0001 はオペコードではありません 0x0002 はオペコードではありません 0x0003 はオペコードです

以下の OpcodesArray を作成し、有効なオペコードと無効なオペコードの間に空のゼロを入れないと、正しい関数を指すことができません。

私の例では、16 ビットのオペコードに応じて呼び出す一連の関数を持つ通信インターフェイスを使用しています。このオペコードは、特定の関数を呼び出す必要があります。

元。

    const unsigned int OpcodesArray[] =   //array of opcodes
{
    0x0008,          //opcode  1
    0x000B,          //opcode 2...
    //... more here
    //... 
    0x00FF,              //opcode 45
    0x01D9,              //opcode 46



  };

void (*OpCodeFunctionPointerArray[TotalNumberOfStates])() = {  //function pointer array

    HOST_GEN_GET_REMOTE_NAME,     //0x0008
    HOST_GEN_SET_SCAN,            //0x000B
    //.....

    HOST_GEN_ERROR_IND,           //0x00FF
    HOST_SPP_SERVICE_CON,         //0x01D9
};


void Process_Packet(void)       /* Process and respond to received packet */
{

    States.OpCode = 0x00FF;   //Example input here

    ServiceStateMachine(States.OpCode);   //service packet

}

void ServiceStateMachine(unsigned int opCode)
{
    OpCodeFunctionPointerArray[opCode]();   //unable to do this because
                                                        //I don't want a huge array 
                                                        //full of zeros         
}


void HOST_GEN_ERROR_IND(void)        //This is the desired function to be called
{


}

これで十分な情報だと思います。オペコード 0x00FF を取得して適切な関数を呼び出す方法がわかりません。0x00FF を取得して、無効なパケットからすべての有効なパケットの間隔を空ける大量のゼロを含む巨大なルックアップ テーブルを持たずに、正しいインデックスを返すにはどうすればよいですか。

ありがとう

4

2 に答える 2

4

関連情報の 2 つの個別の配列を持つ代わりに、各ペアを にグループ化できますstruct

struct operation {
    unsigned short opcode;
    void (*function)();
};

次に、それらの配列を持つことができます:

struct operation opers[] = {
    { <opcode>, <function> },
    { <opcode>, <function> },
    ...
};

オペコードを検索するには、オペコードでソートされているという事実を利用して、バイナリ検索を使用できます。

struct operation *op = bsearch(opers, <number of opcodes>, sizeof(struct operation), op_compar);

このop_compar関数はbsearch、配列の 2 つの要素を比較するために使用されます。

int op_compar(const void *a, const void *b) {
    const struct operation *op1 = a, *op2 = b;
    return op1->opcode - op2->opcode;
}

bsearch対数時間で実行する必要があるため、(順次検索と比較して) 非常に高速です。

于 2013-07-25T20:07:28.280 に答える
2
  1. 使用されるオペコードの数より少し大きい配列を作成します (おそらく 1.5 から 2X)。
  2. 配列にインデックスを付けるハッシュ関数を作成します。
  3. ハッシュ インデックスからエントリを再確認します。一致しない場合は、次のエントリを参照してください。正しいものが見つかるまで探し続けてください。十分な大きさのテーブルがあれば、衝突が多すぎることはありません。
于 2013-07-25T20:07:23.323 に答える