为什么我不能从C中返回的结构调用函数指针?

时间:2016-11-16 16:00:03

标签: c pointers

好的,所以我几周只做C,我遇到了一些问题。我有一个充满Bsig指针的优先级队列。作为一项附加功能,我希望每当弹出Bsig时,我们都会执行自定义函数。

typedef struct bsig{
// some more fields here, but they're not important
    struct onpop_t *on_pop;
} Bsig;

typedef struct onpop_t {
    struct onpop_t *next;
    int (*do_on_pop)(Bsig *caller);
} Onpop;

int pop(SigPQ *q, Bsig* ret_sig){
    if (q->size < 1){
        return 0;
    }
    Bsig* signal = q->signals[0];
    assert(signal);
    q->signals[0] = q->signals[q->size-1];
    q->size--;
    sigpq_heapify(q,0);

    if(signal->on_pop){
        signal->on_pop->do_on_pop(signal);
    }
    ret_sig = signal;
    return 1;
}

基本上,只要我们调用pop,就应该启动do_on_pop函数。此外,pop接收一个信号指针,该指针被从队列中弹出的任何内容覆盖。所有这些都发生在main.c包含的两个文件中。以下是来自main(其中testpop是一个自定义函数,juts随机打印 - 它在main.c文件中声明和定义):

Bsig *sig1 = new_signal(1000, 0);
Onpop *onpop1 = malloc(sizeof(Onpop));
onpop1->do_on_pop = &testpop;
sig1->on_pop = onpop1;
push(pq, sig1);

Bsig *ret_sig;
pop(pq,ret_sig);

到目前为止一切都很好 - 自定义函数testpop被调用。但

ret_sig->on_pop->do_on_pop(ret_sig);
来自main的

给出了分段错误!我不明白为什么。 ret_sig地址和信号地址应该相同,并且函数调用是相同的 - 唯一的区别是一个从main调用,一个从包含的.c文件调用。任何人都可以发光吗?

1 个答案:

答案 0 :(得分:2)

您需要通过引用明确传递ret_sig

int pop(SigPQ *q, Bsig** ret_sig){
    if (q->size < 1){
        return 0;
    }
    Bsig* signal = q->signals[0];
    assert(signal);
    q->signals[0] = q->signals[q->size-1];
    q->size--;
    sigpq_heapify(q,0);

    if(signal->on_pop){
        signal->on_pop->do_on_pop(signal);
    }
    *ret_sig = signal;
    return 1;
}

并传递ret_sig

的地址
Bsig *ret_sig;
pop(pq,&ret_sig);

或者更改函数以返回指针而不是int(更干净):

Bsig *pop(SigPQ *q){
    if (q->size < 1){
        return NULL;
    }
    Bsig* signal = q->signals[0];
    assert(signal);
    q->signals[0] = q->signals[q->size-1];
    q->size--;
    sigpq_heapify(q,0);

    if(signal->on_pop){
        signal->on_pop->do_on_pop(signal);
    }
    return signal;
}

并指定返回值:

Bsig *ret_sig = pop(pq);