代码之家  ›  专栏  ›  技术社区  ›  Chris Lutz

C varargs-VA_复制问题

  •  6
  • Chris Lutz  · 技术社区  · 15 年前

    我在用C语言编写一个函数,它接受可变数量的参数。

    size_t myprintf(char *fmt, ...);
    

    到目前为止,一切都很好。我已经决定,最好以正确的方式做事情,并制作一个采用可变参数的版本,以及另一个采用 va_list .

    size_t myprintf(char *fmt, ...);
    size_t myvprintf(char *fmt, va_list args);
    

    不难做到。除了 my_vprintf() 需要发送 args 输出到两个不同的功能(第一个到 snprintf() 长度为0以确定我们需要多少空间,然后 sprintf() 在我们分配了这么多房间之后)。我这样做 va_copy .

    size_t myvprintf(char *fmt, va_list args)
    {
        va_list args2;
        va_copy(args, args2);
        // do stuff with args2
        va_end(args2);
        // do more stuff with args
    }
    

    这一切都是好的和花哨的,但C99有点执行不力。如果可能的话,我希望我的代码也能在C89中工作,并且能够在尽可能多的编译器和平台上工作。我现在以后有这个 #include <stddef.h> 但在任何代码之前:

    #ifndef va_copy
    # ifdef __va_copy
    #  define va_copy(a,b) __va_copy(a,b)
    # else /* !__va_copy */
    #  define va_copy(a,b) ((a)=(b))
    # endif /* __va_copy */
    #endif /* va_copy */
    

    我相信 ((a)=(b)) 是不可靠的,也许我应该使用 memcpy() 或者类似的东西,但是这仍然是在“如果你不支持C99,我希望它能工作”的水平上,而不是“如果你不支持C99,不要害怕”(这是我想要的)。有没有什么好办法克服这个限制?我看到了一些解决方案- VAI表 接受一个参数并递归的函数,传递 VAI表 两次这样就可以制作两个单独的副本,等等。-但我不知道它们的工作效果如何(如果我只想调用 vsnprintf() 现在,会吗?).

    所以我转向你,stackoverflow用户。还有什么我可以做的来提供C89兼容性,或者用户没有 虚拟拷贝 __va_copy (无可否认,这两者之间的差距太小了)就要把它吸进去然后拿走吗?

    1 回复  |  直到 8 年前
        1
  •  3
  •   AProgrammer    15 年前

    (a)=(b) 不可靠。甚至超过两个 va_list 是(公共函数将是一个简单的包装器)作为va_列表可以是类似的:

    typedef __va_list_impl va_list[1];
    

    在其中一个上执行va_arg将修改另一个(我似乎记得Solaris使用了这样的东西,啊,注册窗口…)。可悲的是,我不知道该怎么做。