两个注意项:
1、linux平台上vsnprintf会破坏va_list变量,需要重新调用va_start,否则可能访问错位崩溃。
2、vsnprintf会留一个字节补0结束,但返回值不包含,所以必须判断返回值小于分配的空间。
具体代码分析:
#include<stdio.h>
#include<stdarg.h>
constexpr size_t AUTO_BUF_LEN = 8;
void myPrintf(const char*format, ...)
{
char buffer[AUTO_BUF_LEN];
char *pBuf = buffer;
va_list args;
va_start(args, format);
int len = vsnprintf(buffer, AUTO_BUF_LEN, format, args);
if (len < AUTO_BUF_LEN) // 返回值不包含结束符,必须 <
{
printf("%s\n", buffer);
}
else
{
printf("重新分配空间:%d\n", len);
// vsnprintf会添加\0结束符,返回值不包含,
char *buf = new char[len + 1];
//va_start(args, format); //linux 上必须加这行,vsnprintf会破坏args
vsnprintf(buf, len + 1, format, args);
printf("%s\n", buf);
delete []buf;
}
va_end(args);
}
int main()
{
printf("小于默认空间测试:\n");
myPrintf("1234567");
myPrintf("%s", "1234567");
myPrintf("%s%d", "12345", 67);
printf("\n等于默认空间测试:\n");
myPrintf("12345678");
myPrintf("%s","12345678");
myPrintf("%s%d", "123456", 78);
printf("\n大于默认空间测试:\n");
myPrintf("123456789");
myPrintf("%s", "123456789");
myPrintf("%s%d", "1234567", 89);
getchar();
}
windows运行: