C中的变量函数

时间:2013-11-17 09:23:57

标签: c avr variadic-functions avr-gcc

我有一个看起来像

的功能
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

这应该有效吗,还是我会以这种方式射击我的脚?

1 个答案:

答案 0 :(得分:4)

C99标准有以下脚注澄清:

  

允许创建指向va_list的指针并将该指针传递给另一个函数,在这种情况下,原始函数可以在另一个函数返回后进一步使用原始列表。

我相信这种行为也是C90的意图,即使标准没有注意到它。 C90理由文件确实有这样的说法:

  

va_list类型不一定是可分配的。但是,函数可以将指针传递给其初始化的参数列表对象,如下所示。

     

...

     必须在要遍历其参数列表的函数体内调用

va_start。然后,该函数可以将指向其va_list对象ap的指针传递给其他函数以进行实际遍历。 (当然,它可以遍历列表本身。)

我认为非常清楚,通过指针访问va_list对象的行为与您期望的一样(在对象实例中维护va_list状态,该地址已被采用来自),即使它没有明确声明原始va_list对象将在指针用法停止的地方拾取。因为它不能以这种方式工作,指向va_list对象的指针必须与指向其他C对象的指针不同。