1

CIでの動作を理解するつもりですが、目的の宛先へのポインターを使用して、任意の型の配列の内容を出力することが期待されるfunction pointers関数ポインターを持つ関数に対してこのプログラムを作成しましたが、機能しません。disp_functionptr

void show_array(void* ptr, void (*disp_function)(void*), int nr_elem) {
    int i=0;
    while(i<nr_elem) {
        (*disp_function) (ptr);
        ptr++;
        i++;
    }
}

プログラムの使用例を次に示します。

void show_movements(Movement* movs, int nr) {
    void (*display_function) (void* ptr) = show_movement;
    show_array(movs, display_function, nr);
}

void show_movement(void* ptr) {
    Movement* ptr2 = NULL;
    ptr2 = (Movement*) ptr;
    printf("%d -> '%s'\n", ptr2->id, ptr2->title);
}

プログラムは最後の関数でクラッシュします。詳細は次のとおりです。

  • 配列には複数の要素があります (> 2)
  • 最初のものは正しく印刷されます
  • 2 番目の要素を印刷しようとすると、プログラムがクラッシュします (デバッグで確認)。

ptr++インクリメントしているときにクラッシュが発生していると思います。また、void*配列構文を使用しようとし(*display_function) (ptr[i]); ましたが、常にエラーが発生しますinvalid use of void expression

誰でも問題の正確な原因を教えてもらえますか?

4

3 に答える 3

3

ポインターをインクリメントするvoid*とき、C はデータ サイズを推測する必要があります。データが と同じサイズであると常に仮定しますchar。これは、最小割り当て可能ユニット (MAU) とも呼ばれます。また、データのサイズを渡して、次のことを行う必要があります。

void show_array(void* ptr, void (*disp_function)(void*), int nr_elem, size_t data_size) {
    int i=0;
    while(i<nr_elem) {
        (*disp_function) (ptr);
        ptr += data_size;
        i++;
    }
}

また、データのサイズは次のように渡す必要があります。

void show_movements(Movement* movs, int nr) {
    void (*display_function) (void* ptr) = show_movement;
    show_array(movs, display_function, nr, sizeof(Movement) );
}
于 2013-05-11T00:26:45.023 に答える
1

void ポインターは、ポインター演算や配列構文を実行するときに扱いにくい場合があります。あなたの質問に対する良い答えは、ここの答えにあります: C の void ポインターのポインター演算

void ポインターは、ポインター演算の目的でバイト ポインターと同等であると見なされるため、型のサイズではなく 1 ずつインクリメントされます。

于 2013-05-11T00:27:30.110 に答える
1

typedef関数ポインタ型の宣言に使用

typedef void (*disp_function)(void*);

現在は型であり、関数パラメーターの一部にすることができます。また void * はインクリメントできません

void show_array(void* ptr, disp_function f, int nr_elem) {
    int i=0;
    while(i<nr_elem) {
        f(ptr);
        //ptr++; // void * cannot be incremented without casting to a concrete type
        i++;
    }
}

void show_movement(void* ptr) {
    Movement* ptr2 = NULL;
    ptr2 = (Movement*) ptr;
    printf("%d -> '%s'\n", ptr2->id, ptr2->title);
}

単純にshow_movement渡すshow_array

void show_movements(Movement* movs, int nr) {
    show_array(movs, show_movement, nr);
}
于 2013-05-11T00:25:02.073 に答える