frm*_*frm 7 c c++ gcc code-conversion
我正在尝试转换一些代码,以便它也在gcc上编译(现在,它仅在MSVC上编译).
我坚持的代码是伪格式化函数,它接受一个格式字符串和零个或多个参数(const char *format, ...)作为输入.然后它将处理一些占用一些参数的占位符,并将其余的传递给vsprintf动态生成的新va_list.
这是生成新的实际代码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);
Run Code Online (Sandbox Code Playgroud)
在我的辩护中,我没有,也绝不会写这段代码.事实上,我认为这是我一生中见过的最讨厌的事情之一.
但是,这个功能非常复杂,非常老,而且非常重要.它也没有被修改多年(好吧,除了现在),所以虽然我想从头开始重写它,我无法证明它需要花费的时间加上它会引入的错误.
所以,我需要一种方法在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将剩余参数传递给vsnprintf(),然后调用va_end()。
我错过了什么吗?为什么要深拷贝?
如果您确实需要深层复制,为什么不直接使用va_start() ,通过va_arg()删除所需的参数,然后将生成的va_list对象传递给vsnprintf()。
(每次调用va_arg都会修改va_list对象,以便下一次调用返回下一个参数。)
或者,您可以只使用va_copy()。(但请务必在其后面加上相应的va_end()。)
附录:另请注意,这些 va_ 宏基于 C89 和 C99 标准。GNU g++ 将支持它们。微软的局限性更大。
跟进TonyK 的评论:
如果您从va_list中取出前 N 项,我上面所说的就有效。如果你把东西从中间拉出来,那就更难了。
没有可移植的方法来构造va_list 。
但是,您可以分解格式字符串,使用它来确定对象类型(双精度型、浮点型、整数型等),并使用其自己的格式字符串(原始格式字符串的一小部分)单独打印每个对象类型。多次snprintf()调用会导致一些开销。但如果这个例程调用得不太频繁,它应该是可行的。
您还可以使用适当制作的va_list打印原始格式字符串的各个部分。换句话说,第一个vsnprintf()调用打印元素 1..3,第二个元素 5..7,第三个 10..13 等。(因为vsnprintf()将忽略va_list上超出其需要的额外元素.您只需要一系列相应的格式字符串片段,并根据每个vsnprintf()调用的需要使用va_arg()从va_list中弹出项目。)
| 归档时间: |
|
| 查看次数: |
4001 次 |
| 最近记录: |