我有一个看起来像
的功能void demo_function_v(const char * mask, va_list ap)
{
for (; *mask; mask++) {
// get one or more args from ap, depending on *mask
}
}
这在AVR系统上运行,该系统具有不同的闪存访问技术。为了复制这个功能,我想提取它的主要部分:
void demo_function_1char(char mask, va_list ap)
{
// get one or more args from ap, depending on mask
}
void demo_function_v(const char * mask, va_list ap)
{
for (; *mask; mask++) {
demo_function_1char(*mask, ap)
}
}
唉,这不能保证工作,如
对象
ap
可以作为参数传递给另一个函数;如果该函数调用带有参数va_arg
的{{1}}宏,则调用函数中ap
的值是不确定的。
这是真的 - 在x86上,它不起作用,在x64上,确实如此。如果它适用于AVR,我明天就能测试。但如果它被描述为“不确定”(据说是一种UB),我宁愿不依赖于此。
因此,我想去另一条赛道:
ap
这应该有效吗,还是我会以这种方式射击我的脚?
答案 0 :(得分:4)
C99标准有以下脚注澄清:
允许创建指向va_list的指针并将该指针传递给另一个函数,在这种情况下,原始函数可以在另一个函数返回后进一步使用原始列表。
我相信这种行为也是C90的意图,即使标准没有注意到它。 C90理由文件确实有这样的说法:
va_list
类型不一定是可分配的。但是,函数可以将指针传递给其初始化的参数列表对象,如下所示。...
必须在要遍历其参数列表的函数体内调用
va_start
。然后,该函数可以将指向其va_list
对象ap
的指针传递给其他函数以进行实际遍历。 (当然,它可以遍历列表本身。)
我认为非常清楚,通过指针访问va_list
对象的行为与您期望的一样(在对象实例中维护va_list
状态,该地址已被采用来自),即使它没有明确声明原始va_list
对象将在指针用法停止的地方拾取。因为它不能以这种方式工作,指向va_list
对象的指针必须与指向其他C对象的指针不同。