c - C回调函数参数范围
问题描述
H.hello 只是这里的一个爱好者。在 JS 绕道之后,我又开始了 C,它教会了我闭包、oop 和其他东西。我通常会制作一些小的代码片段,以便以后参考或重用。那么在下面的代码中,编译器为什么说计数器未声明是有原因的,因为它被引用为回调函数参数的参数?为了使这项工作,1. 我可以将 counter 设为全局变量,这可行,但这不是最佳实践。2. 我可以在 main 中移动调用者函数,但我想避免这种情况。3. 将计数器作为第四个单独的指针参数传递,但是在这种情况下,我真的不知道应该用什么巫术来调用 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;
}
解决方案
那么在下面的代码中,编译器为什么说计数器未声明是有原因的,因为它被引用为回调函数参数的参数?
我想你的意思是在 function popArr()
。是的,当然是有原因的。在popArr()
中,该符号counter
仅出现在回调函数的原型中,并且该出现的范围仅限于它出现的原型。的正文中没有具有该名称的符号popArr()
。
counter
该原型中符号的不同外观,在 functiongenerator()
中,并且main()
全部具有不同的、不重叠的范围。尽管重用了相同的名称,但它们彼此不相关。
一般来说,我对如何使用带参数的回调而不使用全局变量或将所有内容放在 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;
}
推荐阅读
- laravel - Undefined class constant 'App\Providers\RouteServiceProvider::HOME'
- python - 给定地图和规则的最佳寻路算法是什么?
- web-scraping - Scrapy - 获取地图信息
- c++ - Why is it possible to modify a static const variable that is declared inside a function?
- .net-core - .NET Core Angular 客户端 SPA 在注销时重定向到 IdentityServer4 IDP 时出现问题
- amazon-web-services - 在多个无服务器文件中引用整个属性 - [object Object] 不存在
- system-calls - PK/Linux 上的 RISC-V ecall syscall 调用约定
- javascript - 有没有办法从android webview中的onclick()函数启动的先前活动中获取元素ID?
- javascript - 如何使下面的方法从构造函数返回所有参数
- c++ - QuickSort 适用于小尺寸向量但不适用于大尺寸