【发布时间】:2016-06-21 14:28:24
【问题描述】:
为了输出格式化的调试输出,我为vsfprint 编写了一个包装器。现在,我想为输出缓冲区分配足够的内存,而不是仅仅声明一个随机的高缓冲区大小(它是一个小型嵌入式平台(ESP8266))。为此,我遍历变量参数,直到找到 NULL。
这很好用,前提是我不要忘记在每个调用中添加一个(char *)NULL 参数。所以,我想,让我们创建另一个包装器,一个仅传递所有参数并添加(char *) NULL 参数的函数:
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // malloc
void write_log(const char *format, ...) {
char* buffdyn;
va_list args;
// CALC. MEMORY
size_t len;
char *p;
if(format == NULL)
return;
len = strlen(format);
va_start(args, format);
while((p = va_arg(args, char *)) != NULL)
len += strlen(p);
va_end(args);
// END CALC. MEMORY
// ALLOCATE MEMORY
buffdyn = malloc(len + 1); /* +1 for trailing \0 */
if(buffdyn == NULL) {
printf("Not enough memory to process message.");
return;
}
va_start(args, format);
//vsnprintf = Write formatted data from variable argument list to sized buffer
vsnprintf(buffdyn, len, format, args);
va_end(args);
printf("%s\r\n",buffdyn);
free(buffdyn);
}
void write_log_wrapper(const char *format, ...) {
va_list arg;
va_start(arg, format);
write_log(format,arg,(char *)NULL);
va_end(arg);
}
int main()
{
const char* sDeviceName = "TEST123";
const char* sFiller1 = "12345678";
write_log_wrapper("Welcome to %s%s", sDeviceName,sFiller1);
write_log("Welcome to %s%s", sDeviceName,sFiller1, (char *)NULL);
return 0;
}
直接调用write_log() 函数可以正常工作(如果您没有忘记NULL 参数)。调用write_log_wrapper() 函数只会显示第一个参数,然后在输出中添加一个“(nu”(垃圾?)。
我做错了什么?这是实现我最初目标的好方法吗?
谢谢。
【问题讨论】:
-
如果你打算写给
stdout,为什么不直接使用vprintf呢?如果您想写入文件(使用vfprintf),则同样如此。然后,您的代码中根本没有缓冲区分配,您不必处理确定有多少参数或缓冲区有多大。 -
您忽略了传递的参数之一不是通过
char *传递的以 NUL 结尾的字符串的可能性。如果您收到int或double怎么办? -
... 或带有 %p 的 NULL
-
原因是,你不能从这个简化的例子中看出,这个函数不仅仅是简单地吐出缓冲区。它还添加了一个时间戳,并通过一个额外的参数,根据该参数添加了一些 ANSI 着色 ;-)。但我想保持示例简单;-)