我在 Arduino 下编码,我想开发串行打印格式化功能,所以我试图使用sprintf未知大小的缓冲区。基本上,我们可以避免谈论 Arduino 及其串行输出,而是考虑将文本写入缓冲区,然后使用printf. 我试过这个:
#include <stdio.h>
#include <stdarg.h>
void printf0( const char* format, ... ) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end( args );
}
void printf1(const char* format,...) {
va_list args;
va_start(args, format);
char buf[vsnprintf(NULL, 0, format, args)];
sprintf(buf, format, args);
printf(buf);
va_end(args);
}
int main()
{
printf0("Hello, %d!\n", 15);
printf1("Hello, %d!\n", 15);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
printf0函数是我在这里找到的一个准确示例。我的尝试是 function printf1,它产生不可预测的数字。上述程序的示例输出是:
Hello, 15!
Hello, 860799736!
Run Code Online (Sandbox Code Playgroud)
args是 a va_list,所以你不能sprintf用它调用。您必须使用vsprintf或vsnprintf:
sprintf(buf, format, args);
Run Code Online (Sandbox Code Playgroud)
应该
vsnprintf(buf, sizeof buf, format, args);
Run Code Online (Sandbox Code Playgroud)
此外,您应该buf在字符串的 0 终止符的大小上加 1 :
char buf[vsnprintf(NULL, 0, format, args) + 1];
Run Code Online (Sandbox Code Playgroud)
似乎第一次调用vsnprintf改变了args,所以你必须添加
va_end(args);
va_start(args, format);
Run Code Online (Sandbox Code Playgroud)
两次通话之间:http :
//ideone.com/5YI4Or
似乎第一次调用vsnprintf改变了args,但你不应该调用va_start两次。你应该va_copy改用,所以添加
va_list args2;
va_copy(args2, args);
Run Code Online (Sandbox Code Playgroud)
初始化后args。也不要忘记打电话va_end(args2);:
链接到va_copy手册页:https : //linux.die.net/man/3/va_copy