Der Codeabschnitt sollte eigentlich wie die "max_neg"-Lösung funktionieren.- if (retval > (max_val - digit) / base) {Hier wird es knifflig. Ich weiß nicht genau, was du hier checkst. Mal
- overflow = 1;
+ if (neg) {
+ if (result > (min_val - digit) / base) {
+ errno = ERANGE;
+ overflow = 1;
+ }
versuchen zu analysieren, was hier passiert:
min_val ist unsigned long long, digit ist int. Für die Subtraktion wird
digit nach unsigned long long konvertiert, d.h. wir rechnen unsigned.
Die unsigned-Varianten lügen hier und geben ihren Maximalwert statt 0
als min_val. In diesem Fall tut der Code also dasselbe wie der
else-Block. Ich glaube, negative und positive Werte gleich zu parsen ist
richtig.
Die signed-Varianten übergeben für min_val ihr Minimum (also eine
negative Zahl), allerdings konvertiert zu einem unsigned long long, der
den Wert nicht repräsentieren kann.
Damit haben wir als Obergrenze für result * base + digit:
* für strtoll(): ULLONG_MAX - LLONG_MIN = (2 64 - 1) - 2 63 = 2 63 - 1
* für strtol(): ULLONG_MAX - LONG_MIN = (2 64 - 1) - 2 32
Ersteres ist falsch, weil -2 63 als Eingabe funktionieren sollte, aber
so ERANGE setzt. Alle anderen Werte sollten in Ordnung sein.
Zweiteres ist vollkommener Blödsinn und lässt viel zu große Eingaben zu.
Die Testfälle werde ich nochmal überprüfen. Vielleicht auch ganz
cool wäre hier die Nutzung von Gcov. So könnte man bestimmen, wie
gut getestet wird.