在这样的函数中:
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));
我发现了this文章,如果它不起作用,会提出不同的方法:
问:我无法获取va_arg来引入类型指针到函数的参数。
A:尝试使用typedef作为函数指针类型。 va_arg宏通常播放的类型重写游戏受到过于复杂的类型(例如指向函数的指针)的阻碍。
就我而言,它适用于两个版本(GCC 5.2.1),这就是为什么我想知道一种方法比另一种更好?当我没有键入指向首先运行的指针时,是否存在一些潜在的错误?
答案 0 :(得分:2)
在某些情况下,使用不带typedef的指针确实会导致问题。
标准说明type
中使用的va_arg
必须以某种方式编写,其中添加后缀*
将创建指向type
的指针:
7.16.1.1 va_arg宏
- 参数 type 应为类型 指定的名称,使得指向具有指定类型的对象的指针的类型可以 只需将* *后缀为类型即可获得。
醇>
因此,要使用兼容代码,在使用函数指针时,应该使用typedef,因为*
不能作为后缀添加到函数指针类型中以创建指向该类型的指针,因为语法不是'有效:
(double)(*)(double)
=&gt; (double)(*)(double)*
但它可以添加到typedef:
dfun
=&gt; dfun*
答案 1 :(得分:2)
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 应该是指定的类型名称,以便指向具有指定类型的对象的指针的类型可以 只需将*
后缀为类型即可获得。如果没有实际的下一个参数,或者 type 与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则行为是未定义的,除了以下情况:
- 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示;
- 一种类型是指向void的指针,另一种是指向字符类型的指针。
因此,va_arg(args, double(*)(double))
不是va_args
的有效调用,因为double(*)(double)*
是语法错误,而不是指向double(*)(double)
的指针类型{{1} }}。因此,需要类型定义符合标准。 GNU C编译器是仁慈的,因为它不需要这种语法限制,但是你的代码可能无法与其他编译器一起编译。