Search code examples
cprintfavrlibc

Problem with sprintf and uint64_t (avr-libc 2.0.0)


I am playing with the function sprintf in avr-libc 2.0.0 and uint64_t, and it seems it doesn't work properly.

The code

uint64_t x = 12ull;
char buffer[30];

int len = sprintf(buffer, "%llu", x);
int buffer_len = strlen(buffer);

returns len == 2(ok) and buffer_len == 0 (wrong!!!).

The same code works perfectly for uint16_t and uint32_t (and also works for the signed version).

What's the problem? Is it a bug in sprintf of avr-libc? (I test the same code in gcc, not in avr-gcc, and it works ok).

Thanks.


Solution

  • The avr-libc does not implement printing with ll printf modifier.

    But the ll length modifier will to abort the output, as this realization does not operate long long arguments.

    Here is a small wrapper which I have written in under 10 minutes:

    #include <stdio.h>
    #include <stdint.h>
    
    char *uint64_to_str(uint64_t n, char dest[static 21]) {
        dest += 20;
        *dest-- = 0;
        while (n) {
            *dest-- = (n % 10) + '0';
            n /= 10;
        }
        return dest + 1;
    }
    
    
    #define LOG10_FROM_2_TO_64_PLUS_1  21
    #define UINT64_TO_STR(n)  uint64_to_str(n, (char[21]){0})
    
    
    int main(void) {
      printf("Hello World\n");
      printf("%s", UINT64_TO_STR(123456789ull));
      return 0;
    }
    

    will output:

    Hello world
    123456789