gpt4 book ai didi

c++ - 如何在 GCC 上创建 va_list?

转载 作者:可可西里 更新时间:2023-11-01 18:37:19 25 4
gpt4 key购买 nike

我正在尝试转换一些代码,以便它也能在 gcc 上编译(现在,它只能在 MSVC 上编译)。

我遇到的代码是伪格式化函数,它接受格式字符串和零个或多个参数作为输入 (const char *format, ...)。然后它将处理 一些 占位符消耗 一些 参数,并将其余部分与动态生成的新 va_list 一起传递给 vsprintf

这是生成新 va_list 的实际代码:

char *new_args = (char *) malloc(sum);
char *n = new_args;

for(int i = 0; i < nArgs; i++)
{
int j = order[i];
int len = _getlen(types[j]);

memcpy(n, args + cumulOffsets[j], len);
n += len;
}

vsprintf(buffer, sFormat.c_str(), new_args);

在我的辩护中,我没有也永远不会编写这段代码。事实上,我认为这是我一生中见过的最骇人听闻的事情之一。

但是,这个函数非常复杂,非常古老,而且非常重要。它也已经多年没有修改(好吧,除了现在)所以虽然我想从头开始重写它,但我无法证明它所花费的时间以及它会引入的错误。

所以,我需要一种方法在 GCC 上做同样的事情。但是 va_list 不是 char * 所以我得到:

error: ISO C++ forbids casting to an array type '__va_list_tag [1]'

最佳答案

我有点迷路了。为什么您需要一个新的动态生成的 va_list?为什么不重用旧的呢?

我相信 vsnprintf() 使用当前的 va_list 对象(如果你可以这样调用它的话)。所以你可以自由地 va_start(),通过 va_arg() 使用你想要的参数,然后通过 va_list 将剩余的参数传递给 < em>vsnprintf(),然后调用va_end()

我错过了什么吗?为什么要深拷贝?

如果你确实需要一个深拷贝,为什么不用 va_start() 新鲜的,通过 va_arg() 删除你想要的参数,然后传递结果 va_list 对象到 vsnprintf()

(每次调用 va_arg 都会修改 va_list 对象,以便下一次调用返回下一个参数。)

或者,您可以只使用 va_copy()。 (尽管一定要在它后面加上相应的 va_end()。)

附录:另请注意,这些 va_ 宏基于 C89 和 C99 标准。 GNU g++ 将支持它们。 Microsoft 的局限性更大一些。


跟进 TonyK 的评论:

如果您从 va_list 中拉出前 N 项,我上面所说的就有效。如果您要从中间拉出元素,那就更难了。

构造 va_list 没有可移植的方法。

但是,您可以将格式字符串分开,用它来确定对象类型( double 、 float 、整数等),然后用它自己的格式字符串(原始格式字符串的一部分)单独打印每个对象.多个 snprintf() 调用会导致一些开销。但是,如果不经常调用此例程,它应该是可行的。

您还可以使用适当制作的 va_list 打印出原始格式字符串的子部分。换句话说,第一个 vsnprintf() 调用打印元素 1..3,第二个元素 5..7,第三个 10..13,等等。(如 vsnprintf() 将忽略 va_list 上超出其需要的额外元素。您只需要一系列相应的格式字符串片段,并使用 va_list 弹出项目em>va_arg() 根据每次 vsnprintf() 调用的需要。)

关于c++ - 如何在 GCC 上创建 va_list?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4535050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com