我有一个功能:
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);
由于写入了多个字节,因此无法工作。 但可能有一些解决方法。
由于
答案 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等。 然后添加所有字节,