Wrapper for printf

2019-07-10 02:55发布

问题:

I am coding under Arduino and I would like to develop serial print formatting function, so I am trying to use sprintf of unknown sized buffer. Basically, we can avoid talking about Arduino and its serial output and consider writing text to a buffer and then printing it by using printf. I've tried this one:

#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;
}

printf0 function is an accurate example I found here. My tries is function printf1, which produces unpredictable number. Example output of the above programme is:

Hello, 15!
Hello, 860799736!

回答1:

args is a va_list, so you cannot call sprintf with it. You have to use vsprintf or vsnprintf:

sprintf(buf, format, args);

should be

vsnprintf(buf, sizeof buf, format, args);

Also you should add 1 to the size of buf for the 0-terminator of the string:

char buf[vsnprintf(NULL, 0, format, args) + 1];

It seems that the first call to vsnprintf changes args, so you have to add

va_end(args);
va_start(args, format);

between the 2 calls: http://ideone.com/5YI4Or

It seems that the first call to vsnprintf changes args, but you should not call va_start twice. You should use va_copy instead, so add

va_list args2;
va_copy(args2, args);

after initializing args. Also do not forget to call va_end(args2); too:

http://ideone.com/loTRNL

Link to the va_copy man page: https://linux.die.net/man/3/va_copy



标签: c arduino