Oh, that works, but the Arduino String library had some features I wanted. Its docs have an explicit example of putting a literal (an even longer one) into the constructor, so... Mysteries!
My default expectation is that it is a footgun that I do not understand.
The alternative is that I've stumbled across a very rare bug in some popular libraries, or else my hardware is cursed in a very specific and reproducible way.
I actually don't see a "Serial.printf(...)" method in these docs [1], but I do see it here [2]. I'm not sure I'm looking at that right docs for your library though.
Just to answer the mystery, it seems the foot-gun is that smaller String()s appear to work "by accident" due to an optimization, and I have to call a method on the String object before passing it onwards. [0]
> I actually don't see a "Serial.printf(...)" method
I think it's coming from the ESP32-specific libraries. Some cursory searching didn't find the spot, but it may be some magical preprocessor directive stuff.
Maybe what's happening is the `printf` function is interpreting the memory address of the `String` object as if it were a pointer to a char array. This leads to it printing seemingly random bytes (which are actually parts of the `String` object's internal data structure) instead of the string content you expect.
IIRC, some string implementations have separate implementations for very short strings vs. longer ones. Similar thing for vectors.
I also see some size-related logic in the (current?) String implementation [0] [1].
String is a class with no virtual methods, and its first data member is a pointer to the underlying buffer [2]. So if Stream.printf unintentionally type-puns String to char*, it might work out okay?
You're only printing 4 bytes because your string is sufficiently short, and the next byte it's reading is 0, since your capacity is small.
If your string were about 17 million bytes long (0x0101'0101 == 16843009 is the first value that causes problems), then your address, capacity, and size would all likely be nonzero, in which case your Arduino would just keep printing bytes until it lucked upon a zero, or overran its buffer so badly that it started trying to read different segments of memory and eventually segfaulted.
> your Arduino would just keep printing bytes until it lucked upon a zero, or overran its buffer so badly that it started trying to read different segments of memory and eventually segfaulted.
I don't think I've ever used an arduino core for something that had an MMU. It should happily keep printing all the way until the end of memory, and either stop there because it's zeros after, or wrap back to the start depending on the board. I have written code to dump out every byte in memory over serial before, just for kicks.
My default expectation is that it is a footgun that I do not understand.
The alternative is that I've stumbled across a very rare bug in some popular libraries, or else my hardware is cursed in a very specific and reproducible way.