2013-01-17 3 views
12

In zlib 1.2.7, Datei inffast.c, Linie 320, gibt es eine Aussage, die ich nicht verstehe:Warum versucht zlib nur eine positive Zeigerdifferenz zu berechnen?

strm->avail_out = (unsigned)(out < end ? 
          257 + (end - out) : 257 - (out - end)); 

Variablen end und out sind zwei Zeiger in den Ausgabepuffer. Diese Aussage macht eine Anstrengung, end - out zu berechnen, wenn end > out und out - end wenn out >= end, aber ich sehe nicht, warum es das tun könnte. Es scheint mir, dass das Endergebnis das gleiche ist, das heißt, könnte die Linie als gut geschrieben worden ist:

strm->avail_out = 257 + (end - out); 

Die Differenz von zwei Zeigern hat einen gezeichneten integralen Typen, ptrdiff_t (C99 6.5.6: 9) und 257 hat den Typ int. Die Addition findet in der Art des höheren Rangs zwischen diesen beiden statt, und ich sehe nicht, wovor der ternäre Operator möglicherweise schützen könnte.

+3

Ich würde mich nicht wundern, wenn die berühmte Portabilität von zlib auch dadurch möglich gemacht wurde, dass * * * nicht auf definiertem Verhalten beruhte, sondern vielmehr überprüft wurde, was die Implementierungen tatsächlich tun. –

+1

Gibt es einen Quellcode Repo mit genug Geschichte, um diese Linie zu beschuldigen und zu sehen, ob es sich von einer anderen Formulierung entwickelt hat? – Potatoswatter

+1

@Potatoswatter Das einzige, was ich gefunden habe, ist in der "Änderungshistorie" in inflate.c "Ändere strm-> next_out [-state-> offset] zu * (strm-> next_out - state-> offset), um Negationsprobleme zu vermeiden Alphas (64 Bit) in inflate.c "aber das erklärt es nicht. Ich kann sehen, wie 'p [-o]' sich von '* (p-o)' mit 'o' einem 32-Bit unsigned int und' p' einem 64-bit Zeiger unterscheiden könnte. Die Aussage in meiner Frage ist etwas anderes. –

Antwort

17

Ihre Beobachtung ist korrekt für C99 sowie C89/C90.

Diese Codezeile wurde vor zehn Jahren geschrieben. An diesem Punkt erlaubt mir meine Erinnerung nur Paranoia als Ausrede zu behaupten. Anscheinend war ich besorgt, dass in einigen Compilern das Ergebnis der Subtraktion zweier Zeiger unsigniert sein könnte. Ich erinnere mich nicht an den Ursprung dieser Besorgnis, oder ob sie irgendeine Grundlage hatte.

Wie für die change history, wurde diese Codezeile von der Stirn von Zeus geboren, wie Sie es heute sehen. Es wurde nicht verändert, seit es geschrieben wurde.