2

使用 C 级变量参数时:

void  example( size_t length, ... )
{
    va_list  list;
    T        x;
    va_start( list, length );
    //...
    x = va_arg( list, T );
    //...
    va_end( list );
}

某些类型在通过“ ...”时会发生变化。例如,afloat变成了double。如果T是这种类型,我应该将原始类型或损坏的类型放入va_arg

如果 C 和 C++ 和/或标准版本的答案不同,请指出。

(快速浏览一下这里表明应该使用 mangled 类型。我希望不会,因为这已经被破坏了,因为它需要用户计算类型,如果原始类型在类型别名后面,这会很痛苦,尤其是别名没有通用的原件,比如size_t。希望我的帖子的标题更易于搜索。)

(经过更多思考,我意识到目标变量必须使用重整类型声明。因此va_arg,如果为真,使用重整类型 in 没有我想象的那么愚蠢。我auto有时会被 C++11 宠坏。)

4

1 回答 1

4

如果 T 是这样一种类型,我应该将原始类型或损坏的类型放入va_arg

如果T是一个需要提升的类型,那么您应该放入转换后的类型,否则程序具有未定义的行为。

如果 C 和 C++ 和/或标准版本的答案不同,请指出。

据我所知,C 和 C++ 都需要这个。


经过更多思考,我意识到必须使用重整类型声明目标变量

不,这不是必须的。由于可以保证对va_arg()宏的“调用”将是您指定为其第二个参数的类型,因此类似于

float f = va_arg(args, double);

会很好,因为va_arg(...)计算为 type 的表达式,double然后将隐式转换为 a float


编辑:一些标准报价。

一、C99,7.15.1.1.2:

[...]如果没有实际的下一个参数,或者类型与实际的下一个参数的类型不兼容(根据默认参数提升),则行为未定义[...]。

二、C++11 工作草案,18.10.3:

ISO C 对va_start()标头中宏的第二个参数的限制<stdarg.h>在本国际标准中有所不同。参数parmN是函数定义的可变参数列表中最右边参数的标识符(就在...之前的那个)。如果parmN使用函数、数组或引用类型声明参数,或者使用与传递没有参数的参数时产生的类型不兼容的类型,则行为未定义。

对我来说,上面的(C++)引用似乎与默认促销的行为无关;但是,我认为通过说“限制不同”,它们意味着除了以下 [above] 子句之外它们是相同的。

于 2013-11-09T13:27:36.137 回答