Abschlussbericht in Kurzfassung:
Punkt 1: Alles ist ok!
Der Kompiler ist in Ordnung.
Er hält sich an der der Stelle an den C++ Standard, wie es sich gehört.
Arduino und sein AVR Core ist auch voll ok.
Punkt 2: Die Aufgabe im Eingangsposting ist defekt.
Es sollen byte addiert werden, soweit ok.
Das Ergebnis soll in einem int landen, da ist der Haken.
Der Sprachstandard bezeichnet den int Überlauf als undefiniert.
Also ist dem Kompiler auch an der Stelle ein undefiniertes Verhalten erlaubt.
Und sowas zeigt sich ja auch, sogar ein überraschendes Verhalten.
Die Berechnung erfolgt nach den Regeln des AVR völlig korrekt. Es werden negative Zahlen berechnet, bzw ergeben sich die korrekten Ergebnisse nach den Regeln des Zweierkomplements.
Allerdings ist der Kompiler der Überzeugung, dass das Ergebnis niemals kleiner 0 sein kann.
(hätte meine damalige Mathe Lehrerin auch für richtig befunden)
Da die Addition von positiven Werten niemals negativ werden kann, darf der Kompiler alle Abhandlungen für negative Zahlen an der Stelle weg optimieren.
Genau das tut er!
Darum wird hier Print::print(long n, int base) alles, was mit negativen Zahlen zu tun hat, gnadenlos entsorgt.
Die Zahl wird so ausgegeben, wie sie als positive long Zahl aussehen würde.
Tata!
Problem erkannt: Aufgabe kaputt.
Alles ist gut.
Wer es gerne möchte, kann dem Kompiler auch über den Parameter -fwrapv mitteilen, dass ein Wraparound stattfindet, bzw. stattfinden kann.
Dann ist die Welt wieder in Ordnung.
Alternativ, folgendes Pragma vor der betreffenden Funktion unterbringen
#pragma GCC optimize ("-fwrapv")
evtl. garniert mit einem Satz push+pop Pragmas.
Schlusswort:
Vorsicht mit dem Vorzeichen behaftetem Überlauf!
Er erzeugt ein undefiniertes Verhalten.
Ebenso Vorsicht mit impliziten und expliziten Casts von negativen Zahlen zu vorzeichenlosen.
Am besten: Meiden, wie der Teufel das Weihwasser.
Link