0

Background

I'm trying to write a wrapper function for snrpintf() on an embedded platform (Arduino) to have a shorthand for writing into a buffer then printing it over the Serial port.

Problem

As long as I write out the full code everything works, but this is rather verbose. So, I decided to write a function for it, which, alas, doesn't work.

It looks like the pointer doesn't get set properly, as the output is total rubbish.

Example

#include <Arduino.h>

#define AVR_PRINTF_BUFF_SIZE 127

void avrPrintf(const char *fmt, ...) {

    char avr_printf_buffer[AVR_PRINTF_BUFF_SIZE] = {};

    va_list args;
    va_start(args, fmt);
    snprintf(avr_printf_buffer, AVR_PRINTF_BUFF_SIZE, fmt, args);
    va_end(args);

    Serial.print(avr_printf_buffer);
}


void setup() {

    Serial.begin(19200);
    delay(1000);

    Serial.println("Without a function:");
    char buffer[AVR_PRINTF_BUFF_SIZE] = {};
    snprintf(buffer, AVR_PRINTF_BUFF_SIZE, "%d.%02d.%02d %02d:%02d:%02d Weekday: %02d\r\n\n", 1985, 5, 15, 14, 0, 32, 3);
    Serial.print(buffer);

    Serial.println("From a function:");
    avrPrintf("%d.%02d.%02d %02d:%02d:%02d Weekday: %02d\r\n", 1985, 5, 15, 14, 0, 32, 3);
}


void loop() {
    ;
}

OUTPUT

Without a function:
1985.05.15 14:00:32 Weekday: 03

From a function:
2139.12594.14643 12590:13618:13369 Weekday: 12590
too honest for this site
  • 12,050
  • 4
  • 30
  • 52
pfabri
  • 885
  • 1
  • 9
  • 25
  • 4
    Aren't you supposed to use [`vsnprintf`](http://en.cppreference.com/w/cpp/io/c/vfprintf) in your function? – Some programmer dude Jun 20 '18 at 16:21
  • And if you're really programming in C++ then I suggest you come up with other more type-safe ways than the old `printf` family. – Some programmer dude Jun 20 '18 at 16:23
  • Related: https://stackoverflow.com/questions/3530771/passing-variable-arguments-to-another-function-that-accepts-a-variable-argument – R Sahu Jun 20 '18 at 16:26
  • Holy cow! Yes, this makes all the difference. I can't believe I spent 3 hours trying to figure out why this wasn't working. I thought `vsnprintf()` was for printing into stdout, but that's `vfprintf()`. Oh, my. Thank's for your help! – pfabri Jun 20 '18 at 16:28
  • @Someprogrammerdude Do you have any pointers I could look into re: more type-safe ways? – pfabri Jun 20 '18 at 16:31

1 Answers1

1

When you use

snprintf(avr_printf_buffer, AVR_PRINTF_BUFF_SIZE, fmt, args);

args becomes an argument to snprintf just like an int or a float. This causes undefined behavior since the object type expected by the format specifier is not found there. You'll need to use vsnprintf instead.

vsnprintf(avr_printf_buffer, AVR_PRINTF_BUFF_SIZE, fmt, args);
R Sahu
  • 204,454
  • 14
  • 159
  • 270