Fragen? Antworten! Siehe auch: Alternativlos
if (*p == '*')Sieht ja an sich OK aus, außer man beschäftigt sich mal mit der Zahlendarstellung in Computern. Im Zweierkomplement gibt es eine negative Zahl (0x80000000 auf 32-bit Systemen), für die es keine Positiv-Darstellung gibt. Wenn man diese Zahl negiert, kommt sie wieder selbst raus. Für abs() bedeutet das:
{
++p;
total_width += abs (va_arg (ap, int));
}
abs(0x80000000) == 0x80000000 == -2147483648Für diesen Code heißt das, daß die offensichtlich unterliegende Annahme falsch ist, daß dieser Code immer nur Zahlen drauf addiert. Insbesondere kann man so den Code dazu kriegen, weniger Platz zu allozieren, als dann am Ende reingeschrieben wird.
Was mich ja besonders irritiert: dieser Code kommt von libiberty, das ist Teil von gcc/binutils/gdb. Das ist noch keinem aufgefallen?
Und als ich gerade dabei war, dachte ich mir, mhh, printf liefert die Anzahl der Zeichen zurück, die er hätte schreiben wollen. Als int. Was, wenn das so groß wird, daß es negativ wird? Sollte printf das abfangen? -1 zurück geben? Mal gucken, was die glibc macht:
#include <stdio.h>Wenn man das Programm aufruft, frißt er ein Gig RAM, läuft 17 Sekunden (auf meinem fetten Athlon 64), und schreibt dann -2147483647.int main() {
printf("%d\n",snprintf(0,0,"%*d %*d",0x40000000,1,0x40000000,1));
}
Ich hab das jetzt für die dietlibc so gemacht, daß *printf dann -1 zurück gibt. Offenbar ist das unter Solaris jetzt schon so, und wenn ich nicht der erste bin, der das so macht, dann trifft mich auch keine Schuld wegen der Kompatibilitätshölle :-)
Ich habe auch gerade eine Mail vom mirBSD-Projekt gekriegt, da hat jemand den Eintrag hier gesehen und nen Patch eingespielt, die liefern jetzt auch -1 zurück. Das war fix, keine zwei Stunden Turnaround!