During a debugging session, I found out that snprintf
is not working as expected when compiling the code with avr-gcc. The example code should simply convert the floating point value 3999.9f
into its character representation.
Here is a minimal test case:
int TestSnprintf(void)
{
const float inputValue = 3999.9f;
/* Print with a fixed width of 6 characters (5 numbers and 1 dot).
The buffer must have a length of 7, because snprintf appends a '\0' at the end. */
char buf[7U] = {0, 0, 0, 0, 0, 0, 0};
const uint8_t bufferSize = 7U;
if(6 != snprintf(buf, bufferSize, "%06.1f", inputValue))
{
return -1;
}
if( buf[0] != '3'
|| buf[1] != '9'
|| buf[2] != '9'
|| buf[3] != '9'
|| buf[4] != '.'
|| buf[5] != '9'
|| buf[6] != '\0')
{
return -2;
}
return 0;
}
int main(void)
{
int retVal = TestSnprintf();
return 0;
}
Compiling this example code with avr-gcc and running it with Atmel Studio 7 gives a return value of -2. This means snprintf
is not working.
What I have tried so far:
- I tested the code on 32 and 64 bit Linux and it works as expected (
TestSnprintf
return the value 0). - I tested the code with Visual Studio 2015 and it worked as expected (
TestSnprintf
return the value 0). The content of
buf
isbuf[0] = 32; buf[1] = 32; buf[2] = 32; buf[3] = 32; buf[4] = 32; buf[5] = 63; buf[6] = 0;
The testing is performed on the device using the JTAG interface. I tried the simulator as well, with the same result.
- No compiler optimization is activated. The code is compiled and debugged with
-O0
.
Here is a screenshot from the debugging session, that demonstrates that the return value is -2.
This demonstrates that buf
is in scope during debugging:
Question
What am I doing wrong?
SOLUTION
First of all thank you all very much for your help! As pointed out by @manilo the following linker options were missing:
-Wl,-u,vfprintf -lprintf_flt -lm
buf
actually contains. – Sulamithlibm
? (-lm
) – Cetology<stdio.h>
included beforehand? – Pitilessbuf
? – Nevermore-lm
did you link it in? – Cetologybuf
around? Can you show the full code? – Nevermoreprintf
family is implemented? In general on such small targets like AVR, using these heavyweights is not a good idea. Better write custom functions for simple conversions and use them. – Cleareyedbuf
is out of scope. – Nevermore