Chris Loonam
Chris Loonam

Reputation: 5745

C vsnprintf() ignoring last argument

I am trying to display a formatted string on a TFT display using a TI C2000 microcontroller. To implement this, I am using the following function.

void text_writeFormatAtPoint(fontHeader_t font, uint16_t x, uint16_t y, textAlignment_t align, char *fmt, ...) {
    va_list lst;
    char s[64];
    va_start(lst, fmt);
    vsnprintf(s, 63, fmt, lst);
    va_end(lst);
    text_writeTextAtPoint(font, s, x, y, align);
}

I call the function with the following line.

text_writeFormatAtPoint(f_12x16, 0, clock->face.y+30, CENTER, "%2d:%02d:%02d", hours, mins, secs);

On a different microcontroller, this works exactly as expected. However, on this one, only the hours and minutes are put into the string, while the seconds place remains at 00. Through debugging I have made sure that the secs variable holds the correct value, and that s is incorrect, not the display code. Is there some feature of vsnprintf() I am overlooking, or could it possibly be a bug with TI's implementation of the function?

If I do the following

text_writeFormatAtPoint(f_12x16, 0, clock->face.y+30, CENTER, "%2d:%02d:%02d:%02d", hours, mins, secs, secs);

The rightmost place updates, but not the normal one.

Upvotes: 0

Views: 137

Answers (2)

Nate Eldredge
Nate Eldredge

Reputation: 58493

You've identified the problem (wrong types), and suggested changing the seconds to %02ld because secs is uint32_t. Technically this is still wrong, since %02ld expects long int. For one thing, this is signed instead of unsigned, and not all systems necessarily encode a small unsigned integer the same way as a signed one. For another, it will break again when you go to another system where long int is something other than 32 bits.

I think a better fix is to cast:

text_writeFormatAtPoint(f_12x16, 0, clock->face.y+30, CENTER, "%2d:%02d:%02d", (int)hours, (int)mins, (int)secs);

Upvotes: 2

Chris Loonam
Chris Loonam

Reputation: 5745

The problem was that secs was declared as uint32_t while hours and mins were uint16_t, so the format specifier had to be %02ld instead. (I'm surprised this had such a significant impact)

Upvotes: 3

Related Questions