1

我打算了解function pointers在 CI 中为一个函数编写此程序的工作,该函数具有一个函数指针,该函数指针disp_function预期打印任何类型的数组的内容,使用指向ptr预期目标的指针,但它不起作用:

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)
  • 第一个打印正确
  • 尝试打印第二个元素时程序崩溃(通过调试验证)

我想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

用于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 回答
1

当您对它们进行指针算术和数组语法时,无效指针可能会很棘手。您的问题的一个很好的答案是这里的答案:C 中 void 指针的指针算术

由于 void 指针被认为等同于用于指针算术的字节指针,因此您将递增 1 而不是类型的大小。

于 2013-05-11T00:27:30.110 回答