为什么使用函数指针导致我的后续程序崩溃?

时间:2013-05-11 00:09:25

标签: c function-pointers

我打算理解CI中function pointers的工作是为一个函数编写了这个程序,该函数有一个函数指针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);
}

程序在最后一个函数中崩溃。具体如下:

  • 该数组有几个元素(&gt; 2)
  • 第一个正确打印
  • 程序在尝试打印第二个元素时崩溃 (通过调试验证)

我认为ptr++导致崩溃,因为我正在递增void*。我也尝试使用数组语法(*display_function) (ptr[i]); 但我总是收到错误invalid use of void expression

任何人都可以告诉我这个问题的确切原因是什么?

3 个答案:

答案 0 :(得分: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) );
}

答案 1 :(得分:1)

使用typedef声明函数指针类型

typedef void (*disp_function)(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);
}

答案 2 :(得分:1)

当您对它们执行指针算法和数组语法时,Void指针可能会非常棘手。您的问题的一个很好的答案在答案:Pointer arithmetic for void pointer in C

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