Home > Back-end >  Why doesn't sprintf want to fill my buffer?
Why doesn't sprintf want to fill my buffer?

Time:09-22

I use sprintf() to fill a buffer and then send this buffer over UART.

I have follow many exemple and use case of sprintf but my code doesn't seems to work

Here is my code example :

#include "stdio.h"
#include "usart.h"
#define Uart husart1

int main(void)
{
    uint32_t m = 3;
    char c = 'A';
    uint32_t o = 1;
    char buffer[256];
    sprintf(buffer, "AT ,%lu,%c,%lu\r\n", m, c, o);
    HAL_UART_Transmit(&Uart, (uint8_t*) buffer, strlen(buffer), 1000);
}

With this piece of code my output is AT ,lu,,lu

Do you have any idea of what is going wrong ?

Edit 1 : When I replace %lu by %d my compilator says this error :

format '%d' expects argument of type 'int', but argument 5 has type 'uint32_t {aka long unsigned int}' [-Wformat=]

So I have had %ld and the buffer send is like AT ,ld,,ld

Edit 2 : When I replace %lu by %u my compilator says this error :

format '%u' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t {aka long unsigned int}' [-Wformat=]

Edit 3: with #include <stdio.h> I have the same errors

Edit 4: regarding the answers I want to keep the uint32_t as my AT parameters can be 32bit long

Edit 5: I tried to cast the type using %d and (int16_t) as follow :

sprintf(buffer, "AT ,%d,%c,%d\r\n", (int16_t) m, c, (int16_t) o);

and this time my resut is "AT , ,A, "

Why does my code is upset with signed or unsigned integer ?

Edit 6:

With the use of inttypes.h, it looks like this :

sprintf(buffer, "AT ,%"PRIu32",%c,%"PRIu32"\r\n", m, c, o);

and my output still look like AT ,lu,,lu

CodePudding user response:

Embedded targets usually use nano implementation of the standard library and it does not support many printf formats.

Simply use %u for uint32_t as uint32_t is the native integer size for the STM32 uCs.

If you want very very "conforming" add the cast to unsigned int.

CodePudding user response:

Correct format specifier for uint32_t is in define macro PRIu32, which expands to correct format specfier string. It's found in inttypes.h. So your code becomes like this (also fixed the include brackets, assuming none of these headers are part of your project, but part of the toolchain):

#include <stdio.h>
#include <inttypes.h>
#include <usart.h>

#define Uart husart1

int main(void)
{
    uint32_t m = 3;
    char c = 'A';
    uint32_t o = 1;
    char buffer[256];
    sprintf(buffer, "AT ,%"PRIu32",%c,%"PRIu32"\r\n", m, c, o);
    HAL_UART_Transmit(&Uart, (uint8_t*) buffer, strlen(buffer), 1000);
}

The macros may look a bit confusing, so an explanation. In C, you can concatenate string literals at compile time by just by putting them one after the other. In other words, "count is %" "lu" " items" produces exactly same string literal as "count is %lu items". And inttypes.h contains a define like #define PRIu32 "u" or whatever is correct format on the platform.


Reference link: https://en.cppreference.com/w/c/types/integer

  • Related