C语言回调函数参数范围

问题描述 投票:-2回答:1

H.ello只是一个业余爱好者。在经历了JS的一个小弯路后,我又开始学习C语言,学会了闭包,oop和其他东西。我通常会做一些小的代码片段,以后可以参考或重用。那么在下面的代码中,有什么原因导致编译器说counter是未声明的,因为它是作为回调函数参数的一个参数引用的呢?为了使这个工作,1. 2.我可以将回调函数移到main里面,但我想避免这样做3.将counter作为第四个独立的指针参数传递,但是在这种情况下,我真的不知道应该用什么方法在main里面调用回调函数popArr。

所以这里是代码。

#include <stdio.h>

// CALLBACKS

/* Caller */
void popArr(int *arr, size_t length, int (*callback)(int *counter)) {
    for (size_t i=0; i<length; i++) {
        arr[i] = callback(&counter);
        printf("arr[%zu] is: %d\n", i, arr[i]);
    }
}

/* A simple generator callback saving counter. */
int generator(int *counter) {
    *counter = *counter+1;
    return *counter*5;
}

/* Main function. */
int main(void) {

    int counter = 1;
    int arr[10];
    popArr(arr, 10, &generator);
    return 0;
}
c callback arguments
1个回答
0
投票

那么在下面的代码中,为什么编译器说counter是未声明的,因为它是作为回调函数参数的一个参数引用的,有什么原因吗?

我猜测你是指在函数 popArr(). 是的,当然是有原因的。 在 popArr()符号 counter 只出现在回调函数的原型中,而且该出现的范围仅限于它所出现的原型。 在该函数的主体中,范围内没有该名称的符号。popArr().

符号的不同表现形式 counter 在该原型中,在功能上 generator()以及在 main() 都有不同的、不重叠的范围。 尽管重用了相同的名称,但它们之间并没有关系。

一般来说,我对如何在不使用全局变量或把所有东西都放在main里面的情况下使用带参数的回调技术感兴趣。

主要有两种情况。

  1. 带有参数的回调是由调用者(popArr() 在你的例子中)被期望选择自己,而
  2. 回调提供者带参数的回调(main() 在您的例子中)预计将具体说明。

这些并不相互排斥。 情况(1)没有特别的要求--调用者只需根据自己的判断,传递任何合适的参数。 情况(2)原则上并不难:提供回调的代码只需要提供适当的参数即可。 对于你的非常简单的情况,即不需要存储参数和回调,它看起来像这样。

void popArr(int *arr, size_t length, int (*callback)(int *), int *counter) {
    // The name of the parameter to (*callback)() is omitted for clarity. It is
    // optional in this context.
    for (size_t i = 0; i < length; i++) {
        arr[i] = callback(counter);  // Note: passing counter, not *counter
        printf("arr[%zu] is: %d\n", i, arr[i]);
    }
}

/* A simple generator callback saving counter. */
int generator(int *counter) {
    *counter += 1;

    return *counter * 5;
}

/* Main function. */
int main(void) {
    int counter = 1;
    int arr[10];

    // It is unnecessary, but not harmful, to use the & operator on the function
    // name.  I think it's better style to omit it.
    // It is necessary to use the & operator on 'counter', but mainly because
    // you want to pass a pointer to counter, as opposed to its value
    popArr(arr, 10, generator, &counter);

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.