[英]Is this the correct way to use va_arg with pointer to function?
在这样的函数中:
typedef double(*dfun)(double);
void tab(double x, int n, ...)
{
va_list args;
va_start(args, n);
printf("%5.2lf \t", x);
for (int i=0; i<n; i++)
{
dfun tmp = va_arg(args, dfun);
printf(" %5.2lf \t", tmp(x));
}
va_end(args);
}
如果我拉这样的论点是错的:
double(*tmp)(double) = va_arg(args, double(*)(double));
我发现这篇文章提出了一种不同的方法,如果它不起作用:
问:我无法让va_arg引入类型指针到函数的参数。
答:尝试使用typedef作为函数指针类型。 va_arg宏通常播放的类型重写游戏受到过于复杂的类型(例如指向函数的指针)的阻碍。
在我的情况下,它适用于两个版本(GCC 5.2.1),这就是为什么我想知道一种方法比另一种更好? 当我没有首先将指针指向函数时,是否存在一些潜在的错误?
在某些情况下,使用不带typedef的指针确实会导致问题。
标准解释说, va_arg
使用的type
必须以某种方式编写,其中添加后缀*
将创建指向type
的指针:
7.16.1.1 va_arg宏
- 参数类型应该是指定的类型名称,以便只需通过将*固定为类型即可获得指向具有指定类型的对象的指针的类型 。
因此,要使用兼容代码,在使用函数指针时,应该使用typedef,因为*
不能作为后缀添加到函数指针类型中以创建指向该类型的指针,因为语法无效:
(double)(*)(double)
=> (double)(*)(double)*
但它可以添加到typedef:
dfun
=> dfun*
va_arg(args, type)
记录为(参见ISO 9899:2011§7.16.1.1¶2):
va_arg
宏扩展为具有指定类型和调用中下一个参数值的表达式。 参数ap
应该已经由va_start
或va_copy
宏初始化(没有为同一个ap重新调用va_end
宏)。 每次调用va_arg宏都会修改ap,以便依次返回连续参数的值。 参数类型应该是指定的类型名称,以便只需通过将*
为类型即可获得指向具有指定类型的对象的指针的类型 。 如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则行为是未定义的,除了以下情况:
- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;
- 一种类型是指向void的指针,另一种是指向字符类型的指针。
因此, va_arg(args, double(*)(double))
不是va_args
的有效调用,因为double(*)(double)*
是语法错误而不是指向double(*)(double)
的指针的类型将是double(**)(double)
。 因此,需要类型定义符合标准。 GNU C编译器是仁慈的,因为它不需要这种语法限制,但您的代码可能无法与其他编译器一起编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.