DarkFranX
DarkFranX

Reputation: 561

Why does PRIx64 print "lx" instead of 16 hex chars?

We've run into an issue at work where we were not able to use the "portable" types from <inttypes.h> (PRIx64) to correctly print a 64-bit unsigned integer in hexadecimal format.

uint64_t serial = 0x12345678;
usb_printf("Serial: %"PRIx64"\n", serial);

where

void usb_printf(const char *fmt, ...)
{
    char string[512];
    uint16_t string_length = 0;
    va_list va;

    va_start(va, fmt);
    string_length = vsnprintf(string, ARRAY_SIZE(string), fmt, va);
    bsp_usb_cdc_send_buf((uint8_t *)string, string_length);
    va_end(va);
}

gives

> Serial: lx

This is running on a LPC55S28 (Cortex-M33), and linked with -specs=nosys.specs -specs=nano.specs using GCC.

By looking at PRIx64 definition, it seems that it was defined as:

#define __INT64 "ll"
#define __PRI64(x) __INT64 __STRINGIFY(x)
#define PRIx64      __PRI64(x)

Why isn't the PRIx64 portable type definition behaving as one would expect on this platform?

Upvotes: 2

Views: 313

Answers (1)

0___________
0___________

Reputation: 67845

newlib-nano does not support float numbers (you need to tell the linker to link the support) and printf does not support long long numbers (and there is no way to add the support).

You must not use nano.specs if you want to printf long long numbers

Nano documentation explicitly says that

     enable-newlib-io-pos-args
     enable-newlib-io-c99-formats
     enable-newlib-io-long-long
     enable-newlib-io-long-double

build options are not supported. So even rebuilding the library with those options will not add the support.

Conclusion:

  1. Do not use newlib-nano
  2. Write your own long long print functions.

General remark: when you program micro-controllers you should forget many things you normally use when programming big machines (like PC computers), especially malloc style allocations and fancy printf formats.

Upvotes: 5

Related Questions