Arduino started off on a small AVR. It supports f-p printing with C++ classes. You can specify how many decimal places but not the overall format width. (it defaults to 2 dec places)
Although you have access to the regular C library, printf() defaults to the cut-price version. Formatting f-p expressions is quite expensive. That is why you see "?" when you try to use "%f"
#if defined(__arm__) //e.g. Zero, Due, STM32
#include <avr/dtostrf.h>
#endif
void setup()
{
Serial.begin(9600);
Serial.println("print Floating Point on Arduino");
Serial.print("regular Serial.print(1.234) ");
Serial.println(1.234);
char buf[40];
Serial.print("sprintf(2.345) ");
sprintf(buf, "%5.2f", 2.345);
Serial.println(buf);
Serial.print("dtostrf(3.456) ");
dtostrf(3.456, 5, 2, buf);
Serial.println(buf);
}
void loop()
{
}
Note that some Arduino "cores" expect you to include "dtostrf.h"
But the standard AVR IDE always knows about dtostrf()
Cores like ARM, ESP32, ESP8266 come with a full-fat printf() so you can use %f easily.
If you want to use a Uno, Mega, ... you will need dtostrf()
dtostrf() can format output nicely
Arduino print() can never pad expressions. Everyone has discovered how nasty integer and hex numbers look.
David.