Ich habe in Dennis Ritchies Buch The C Programming Language gelesen, dass int
eine Variable verwendet werden muss, um EOF zu halten - um sie so groß zu machen, dass sie EOF-Werte enthalten kann - nicht char
. Der folgende Code funktioniert jedoch einwandfrei:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Wenn keine Eingabe mehr erfolgt, wird getchar
EOF zurückgegeben. Und im obigen Programm kann die Variable c
mit dem Typ char sie erfolgreich halten.
Warum funktioniert das? Gemäß der Erklärung in dem oben erwähnten Buch sollte der Code nicht funktionieren.
0xff
. Das Speichern des Ergebnissesgetchar()
inint
löst dieses Problem. Ihre Frage entspricht im Wesentlichen der Frage 12.1 in den häufig gestellten Fragen zu comp.lang.c. Dies ist eine hervorragende Ressource. (Sollte auchmain()
seinint main(void)
, und es würde nicht schaden,return 0;
vor dem Abschluss ein hinzuzufügen}
.)Antworten:
Ihr Code scheint zu funktionieren, da die impliziten Typkonvertierungen versehentlich das Richtige bewirken.
getchar()
Gibt einint
mit einem Wert zurück, der entweder in den Bereich von passtunsigned char
oder istEOF
(was negativ sein muss, normalerweise ist es -1). Beachten Sie, dass esEOF
sich nicht um ein Zeichen handelt, sondern um ein Signal, dass keine weiteren Zeichen verfügbar sind.Beim Speichern des Ergebnisses von
getchar()
inc
gibt es zwei Möglichkeiten. Entweder kann der Typchar
den Wert darstellen. In diesem Fall ist dies der Wert vonc
. Oder der Typchar
kann den Wert nicht darstellen. In diesem Fall ist nicht definiert, was passieren wird. Intel-Prozessoren hacken nur die hohen Bits ab, die nicht in den neuen Typ passen (wodurch der Wert von Modulo 256 effektiv reduziert wirdchar
), aber darauf sollten Sie sich nicht verlassen.Der nächste Schritt ist der Vergleich
c
mitEOF
. AlsEOF
ein istint
,c
wird ein überführt werdenint
als auch, in den gespeicherten Wert zu bewahrenc
. Wennc
der Wert von gespeichert werden kannEOF
, ist der Vergleich erfolgreich. Wenn der Wertc
jedoch nicht gespeichert werden kann, schlägt der Vergleich fehl, da bei der KonvertierungEOF
in den Typ ein nicht behebbarer Informationsverlust aufgetreten istchar
.Es scheint, dass Ihr Compiler den
char
Typ signiert und den WertEOF
klein genug gemacht hat, um hinein zu passenchar
. Wenn Siechar
nicht signiert wären (oder wenn Sie verwendet hättenunsigned char
), wäre Ihr Test fehlgeschlagen, daunsigned char
der Wert von nicht gehalten werden kannEOF
.Beachten Sie auch, dass es ein zweites Problem mit Ihrem Code gibt. Da
EOF
es sich nicht um ein Zeichen selbst handelt, sondern Sie es in einenchar
Typ zwingen , gibt es sehr wahrscheinlich ein Zeichen, das als solches falsch interpretiert wird,EOF
und für die Hälfte der möglichen Zeichen ist es undefiniert, ob sie korrekt verarbeitet werden.quelle
char
Werte außerhalb des BereichsCHAR_MIN
..CHAR_MAX
wird benötigt , entweder eine Implementierung definierten Wert zu ergeben, einen Bitmuster ergeben , die die Implementierung definiert als Falle Darstellung oder ein implementierungsspezifischen Signal erhöhen. In den meisten Fällen müssten Implementierungen viel zusätzliche Arbeit auf sich nehmen, um etwas anderes als die Reduzierung des Zweierkomplements zu tun. Wenn die Mitglieder des Normungsausschusses der Idee(signed char)x
sollte als klarer und genauso sicher angesehen werden wie((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) Wie es ist, sehe ich keine Wahrscheinlichkeit dafür Compiler, die jedes andere Verhalten implementieren, das dem heutigen Standard entspricht; Die einzige Gefahr wäre, dass der Standard geändert wird, um das Verhalten im angeblichen Interesse der "Optimierung" zu brechen.int i=129; signed char c=i;
ist ein solches Verhalten. Relativ wenige Prozessoren haben eine Anweisung, diec
gleich ist,i
wenn sie im Bereich von -127 bis +127 liegt, und eine konsistente Zuordnung anderer Werte voni
zu Werten im Bereich von -128 bis +127 ergibt, die sich von der Zweierkomplementreduktion unterscheiden, oder. ..