首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于C回调函数的参数,哪个更好: va_list,还是省略号?

问对于C回调函数的参数,哪个更好: va_list,还是省略号?
EN

Stack Overflow用户
提问于 2010-10-27 21:43:19
回答 2查看 2.3K关注 0票数 2

我的图书馆提供了一个回调点,我的图书馆用户可以在那里注册以获取信息。回调的一般形式是一个int,后跟各种参数,这些参数的类型取决于int值。因此,我定义了回调类型和函数来设置它,如下所示。

代码语言:javascript
复制
typedef void (* callback_func_t)(int type, ...);
void set_callback_func(callback_func_t callback);

在我的库中,我一直在调用这个函数,它是用户设置的函数,或者是我提供的默认函数。它起作用了。

现在,我想添加一个间接层,以便能够调用多个已注册的回调。问题是,我的内部回调函数仍然接受省略号参数,也必须调用带省略号的回调函数。因此,我的内部函数必须解释type,从va_list解压参数,并将它们作为参数提供给callbacj函数。

代码语言:javascript
复制
void internal_callback(int type, ...) {
    va_list args;
    va_start(args, type);
    switch (type) {
    case 0: call_callback(type, va_arg(args, int)); break;
    // ...
    }
    va_end(args);
}

但是,在用户的回调实现中,根据type的值,也会有相同的va_list使用和参数解释。解决方案是将va_list作为参数直接传递给回调函数,使内部回调函数的实现变得显而易见。

代码语言:javascript
复制
typedef void (* callback_func_t)(int type, va_list args);

我的问题是:定义一个以va_list为参数的回调函数类型是一种好的做法吗?我可以像上面那样定义我的回调函数类型,但是与上面的定义相比,它的优缺点是什么?

EN

回答 2

Stack Overflow用户

发布于 2010-10-27 22:00:24

我假设有一个有限的和已知数量的类型?如果是这样的话,为什么不使用枚举和联合来实现某种级别的类型安全,顺便说一句,这也可以解决您的问题:

代码语言:javascript
复制
enum callback_arg_type { INT_ARG, DOUBLE_ARG, VECTOR_ARG };

union callback_arg
{
    int as_int;
    double as_double;
    struct { double x, y, z; } as_vector;
};

typedef void (*callback_func_t)(
    enum callback_arg_type type, union callback_arg arg);

根据参数大小的不同,传递一个指针可能是个好主意。您还可以提供一些宏,以便为回调调用提供更好的语法,但如果它们只从您的库中调用,则可能不值得这样做:

代码语言:javascript
复制
union callback_arg arg = { .as_int = 42 };
callback_fn(INT_ARG, arg);

它本身是相当短的。

票数 4
EN

Stack Overflow用户

发布于 2010-10-27 22:18:44

我会选择va_list版本。用户已经在处理处理va_list的可怕问题,所以您不会通过对他们隐藏它来保存任何东西。

此外,使用列表而不是尝试重新传递参数将减少堆栈的使用。如果您必须将参数重新传递给它们的函数,它将创建所有这些参数的新副本,但传递va_list类型将只使用堆栈中已有的这些参数的实例。

最后,您的代码将变得更简单(如果我对问题的理解正确的话),并且您将使每个用户不必调用va_start和va_end (对于大多数stdarg实现,这可能不会对其函数中的输出代码进行太多更改),但除此之外,他们都必须键入这些调用,并且(取决于stdarg在平台上的实现方式),他们将需要确保在返回之前确实调用了va_end (如果在出现错误的情况下提前返回,则很容易遗漏)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4033899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档