It is a known problem that the data types of arguments in a functions having a "...
" argument list matter because the compiler is normally not able to automatically adjust the data types.
Maybe some compilers will automatically detect the format specifiers in printf
and adjust the data types in the arguments accordingly. GNU C for example will parse the string and print a warning message that the data types do not match but it does not adjust the data types.
If you don't use the correct data type you'll definitely get bad results.
Obviously %d
means 16 bit for your compiler but 1
is some other data type (e.g. 8 bit).
Maybe with your compiler an argument list of the following form:
(uint8)a, (uint16)b, (uint8)c, (uint8)d
May be stored in the memory like this:
a, high_byte_of(b), low_byte_of(b), c, d
If the function expects c
to be a 16-bit value the function will interpret the c
in the memory as the high 8 bits of c
and it will interpret d
in the argument list as low 8 bits of d
...
So in your case if you do the following:
foo("%d, %d", 1, 2, 3, 4);
The memory would look like this:
1, 2, 3, 4, ...
... and vsprintf
will interpret this as 0x102 and 0x304, not as 1 and 2.
Of course in the RAM the 4
is followed by some other bytes which are not related to this part of the program so the RAM content maybe looks like this:
1, 2, 3, 4, 19, 32, 54, 21, 32, ...
In your case the first byte in the RAM would be a 1
followed by some "random" data (data not related to the function call).
Obviously the first byte after the 1
is a 0
so the vsprintf
function interprets this as 0x0100.
If you use (uint16)1
as arguments the byte 0
followed by 1
will be written to the RAM so vsprintf
interprets this as 0x0001.