使用C级变量参数时:
void example( size_t length, ... )
{
va_list list;
T x;
va_start( list, length );
//...
x = va_arg( list, T );
//...
va_end( list );
}
某些类型在通过“...
”时会被更改。例如,float
变为double
。如果T
是这样的类型,我应该将原始类型或受损的类型放入va_arg
吗?
如果C和C ++和/或标准修订版的答案不同,请注明。
(这里的快速浏览表明应该使用受损的类型。我希望不会,因为它已经被破坏,因为它需要用户计算类型,如果原始类型在类型别名后面,这是一种痛苦,尤其是没有通用原创的别名,例如size_t
。希望我的帖子的标题更易于搜索。)
(更多的想法,我意识到目标变量必须用损坏的类型声明。所以使用va_arg
中的受损类型,如果是真的,就比我想象的要愚蠢。我被C宠坏了有时候是++ 11的auto
。)
答案 0 :(得分:4)
如果T是这样的类型,我应该将原始类型或受损的类型放入
va_arg
吗?
如果T
是受推广的类型,那么您应该输入转换后的类型,否则程序会有未定义的行为。
如果C和C ++和/或标准修订版的答案不同,请注明。
据我所知,C和C ++都需要这个。
经过深思熟虑,我意识到目标变量必须使用损坏类型
进行声明
不,这不是必须的。由于保证va_arg()
宏的“调用”将是您指定为其第二个参数的类型,因此类似
float f = va_arg(args, double);
完全没问题,因为va_arg(...)
会计算出double
类型的表达式,然后会隐式转换为float
。
编辑:一些标准报价。
予。 C99,7.15.1.1.2:
[...]如果没有实际的下一个参数,或者type与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则行为未定义[...]
II。 C ++ 11工作草案,18.10.3:
ISO C对标题
va_start()
中<stdarg.h>
宏的第二个参数的限制在本国际标准中有所不同。参数parmN
是函数定义的变量参数列表中最右边的参数的标识符(恰好在......之前)。如果使用函数,数组或引用类型声明参数parmN
,或者使用与传递没有参数的参数时产生的类型不兼容的类型,则行为未定义。 / p>
对我来说,上面的(C ++)引用似乎与默认促销的行为无关;但是,我认为通过说“限制是不同的”,它们意味着它们是相同的,除了以下[上面]条款。