省略号函数参数的字节大小

时间:2012-04-24 12:20:10

标签: c++ c printf variadic-functions

我有一个功能:

static int myprintf(const char* fmt, ...)

我想知道所有myprintf参数的大小(以字节为单位),如果它们被打印到缓冲区。 我需要动态分配一个数组,我可以打印参数(使用sprinf_vsprinf) 例如,在32位操作系统中,对于myprintf(“%d%c”,10,“a”); myprintf参数的大小为5。

我尝试实现它:

va_list ap;

va_start(ap, fmt);

myArgSize(ap);

有人可以建议如何实施myArgSize。

我被告知尝试这样的事情

char c;
int len = ::_vsnprintf(&c, 1, fmt, ap);

由于写入了多个字节,因此无法工作。 但可能有一些解决方法。

由于

4 个答案:

答案 0 :(得分:1)

嗯......关于参数的类型和顺序的唯一信息是在第一个参数中;这就是为什么需要它。

对于类似printf()的函数,您需要单步执行格式化字符串,解析每个% - 代码,并添加相应类型的大小。这不会是微不足道的。请务必处理期望%hd而不是short的{​​{1}}之类的内容。此外,当值传递给可变参数函数时会发生转换。

答案 1 :(得分:1)

您可以使用vasprintf将所有格式设置为适当大小的缓冲区,它将分配(并且您必须free)。

或者,vsnprintf可用于获取将打印的字符串printf的长度:

int n = vsnprintf(NULL, 0, fmt, args);

这是因为如果有足够的空间,它会返回打印的字节数。在这种情况下,它无法打印任何内容,但无论如何都会返回数字。

答案 2 :(得分:1)

即使您的大部分问题都是关于传递给三元函数的参数的大小,但在我看来,您实际上对输出缓冲区需要的大小感兴趣。尝试以下内容:

va_list ap;

va_start(ap, fmt);

int len = ::vsnprintf( NULL, 0, fmt, ap);
if (len < 0) abort();

char* buffer = (char*) malloc( len + 1);
if (!buffer) abort();

::vsnprintf( buffer, len+1, fmt, ap);

va_end();

但是,如果您的平台没有符合C99标准的vsnprintf()(例如,MSVC),那么您将不得不进行一些调整。对于MSVC您可以尝试传入一个带有猜测的缓冲区(可能是strlen(fmt)+1 + (10 * number_of_percent_signs_in_fmt),或者只是以大小应该覆盖99%的情况开始 - 可能是200),然后增加猜测直到它起作用。或者您可以尝试类似the snprintf() family of functions by Holger Weiss的内容。

答案 3 :(得分:-2)

您可以使用sizeof(type_name)并使用for循环遍历所有参数, type_name是任何c数据类型,如int,float,long等。 然后添加所有字节,