C 回调函数参数范围
C callback function argument scope
H.ello 只是这里的爱好者。在绕了一点 JS 的弯路之后,我又开始了 C 语言,它教会了我闭包、oop 和其他东西。我通常制作一些小代码片段,供以后参考或重用。那么在下面的代码中,为什么编译器说计数器未声明是有原因的,因为它被引用为回调函数参数的参数?
为了使这项工作,
1. 我可以让计数器成为一个全局变量,这可行,但不是最佳实践。
2. 我可以在 main 中移动调用函数,但我想避免这种情况。
3. 将计数器作为第 4 个单独的指针参数传递,但是在那种情况下,我真的不知道我应该用什么巫术来调用 main 中的调用函数 popArr。
一般来说,我对如何在不使用全局变量或将所有内容都放在 main 中的情况下使用带参数的回调的技术感兴趣。
代码如下:
#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;
}
So in the code below is there a reason why the compiler says counter
is undeclared, as it is referenced as an argument of the callback
function argument?
我猜你的意思是在函数 popArr()
中。是的,当然是有原因的。在popArr()
中,符号counter
只出现在回调函数的原型中,而且出现的范围仅限于它出现的原型。在 popArr()
.
的正文范围内没有具有该名称的符号
符号 counter
在该原型、函数 generator()
和 main()
中的不同外观都有不同的、不重叠的范围。尽管重复使用相同的名称,但它们彼此无关。
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
主要有两种情况:
- 带有调用者(
popArr()
在你的例子中)应该自己选择的参数的回调,
- 回调提供者(在您的示例中为
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;
}
H.ello 只是这里的爱好者。在绕了一点 JS 的弯路之后,我又开始了 C 语言,它教会了我闭包、oop 和其他东西。我通常制作一些小代码片段,供以后参考或重用。那么在下面的代码中,为什么编译器说计数器未声明是有原因的,因为它被引用为回调函数参数的参数? 为了使这项工作, 1. 我可以让计数器成为一个全局变量,这可行,但不是最佳实践。 2. 我可以在 main 中移动调用函数,但我想避免这种情况。 3. 将计数器作为第 4 个单独的指针参数传递,但是在那种情况下,我真的不知道我应该用什么巫术来调用 main 中的调用函数 popArr。 一般来说,我对如何在不使用全局变量或将所有内容都放在 main 中的情况下使用带参数的回调的技术感兴趣。
代码如下:
#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;
}
So in the code below is there a reason why the compiler says counter is undeclared, as it is referenced as an argument of the callback function argument?
我猜你的意思是在函数 popArr()
中。是的,当然是有原因的。在popArr()
中,符号counter
只出现在回调函数的原型中,而且出现的范围仅限于它出现的原型。在 popArr()
.
符号 counter
在该原型、函数 generator()
和 main()
中的不同外观都有不同的、不重叠的范围。尽管重复使用相同的名称,但它们彼此无关。
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
主要有两种情况:
- 带有调用者(
popArr()
在你的例子中)应该自己选择的参数的回调, - 回调提供者(在您的示例中为
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;
}