Wrap-around-Erklärung für signed und unsigned Variablen in C?
Lese ich ein bisschen in C Spezifikation, dass die vorzeichenlose Variablen( insbesondere unsigned short int) führen Sie eine sogenannte wrap-around - auf integer-überlauf, obwohl ich konnte nicht finden, dass irgendetwas unterschrieben Variablen außer, dass ich Links mit Undefiniertes Verhalten. Mein professor sagte mir Ihre Werte auch erhalten gewickelt.( vielleicht hat er nur gemeint, gcc ) dachte ich die bits einfach abgeschnitten und die Stückchen, die ich verließ mit mir etwas seltsam Wert?! Also, kann mir jemand erklären, was wrap-around ist, und wie ist es anders als nur mit dem abschneiden von bits.
Ihr professor ist falsch, es sei denn, seine Aussage, dass Werte, die wrap-around war qualifiziert, um die spezifischen C-Implementierungen, ggf. mit bestimmten flags in Bezug auf Optimierung oder Semantik.
was meinst du spezielle c-Implementierung und wie ist es im Allgemeinen?
Der C-standard nicht definiert, was passiert, wenn integer-überlauf Auftritt. Jedoch, eine C-Implementierung definieren kann, was passiert. C-Implementierungen zulässig sind, gehen Sie über den C standard. So ist es zum Beispiel möglich, dass der GCC könnte eine Erklärung sagen: "Wenn integer-überlauf tritt auf, und die
was meinst du spezielle c-Implementierung und wie ist es im Allgemeinen?
Der C-standard nicht definiert, was passiert, wenn integer-überlauf Auftritt. Jedoch, eine C-Implementierung definieren kann, was passiert. C-Implementierungen zulässig sind, gehen Sie über den C standard. So ist es zum Beispiel möglich, dass der GCC könnte eine Erklärung sagen: "Wenn integer-überlauf tritt auf, und die
-fSomething
- Schalter verwendet werden, bei der Erstellung, dann das Ergebnis ist verpackt in zwei der Ergänzung." Oder, wenn GCC nicht Zustand, dann Fred Doe können sich aus den GCC-Quellen, ändern Sie Sie wie gewünscht, und stellen Sie ein neues Fred-spezifische version des GCC, der verhält sich in einer bestimmten Art und Weise.InformationsquelleAutor orustammanapov | 2013-11-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vorzeichenbehaftete integer-Variablen haben keine wrap-around-Verhalten in der C-Sprache. Ganzzahl-überlauf bei arithmetischen Berechnungen produziert Undefiniertes Verhalten. Hinweis: BTW, den GCC-compiler, den Sie erwähnt haben, ist bekannt für die Umsetzung strengen überlauf Semantik in Optimierungen, das heißt, er nutzt die Freiheit, die so undefiniert Verhalten Situationen: GCC-compiler geht davon aus, dass vorzeichenbehaftete integer-Werte nie herum wickeln. Das bedeutet, dass GCC eigentlich geschieht zu einem der Compiler in dem Sie nicht verlassen sich auf wrap-around-Verhalten von signed-integer-Typen.
Beispielsweise GCC-compiler kann davon ausgehen, dass für die variable
int i
die folgende Bedingungist äquivalent zu einem bloßen
Dies ist genau das, was strengen überlauf Semantik bedeutet.
Unsigned integer-Typen implementieren modulo-Arithmetik. Der modulo gleich
2^N
woN
ist die Anzahl der bits in dem Wert Darstellung der Art. Aus diesem Grund unsigned integer-Typen in der Tat erscheinen, um wrap-around auf überlauf.Jedoch in der Sprache C nie führt arithmetische Berechnungen in Domänen kleiner als der
int
/unsigned int
. Geben Sieunsigned short int
dass Sie erwähnen in Ihrer Frage wird in der Regel gefördert werden, gebenint
in Ausdrücken, bevor irgendwelche Berechnungen beginnen (vorausgesetzt, dass der Bereich derunsigned short
passt in die Reihe derint
). Was bedeutet, dass 1) die Berechnungen mitunsigned short int
wird vorgeformt werden, die im Bereich derint
, mit überlauf passiert, wennint
überläuft, 2) überlauf bei solchen Berechnungen führen zu undefiniertem Verhalten, nicht zu wrap-around-Verhalten.Zum Beispiel, dieser code erzeugt ein wrap-around -
während dieser code
führt zu undefiniertem Verhalten.
Wenn keine
int
überlauf passiert, und das Ergebnis wird zurück konvertiert, um eineunsigned short int
geben, es wieder reduziert wird, indem modulo2^N
, die angezeigt wird, als wenn der Wert gewickelt.short int y = 511, z = 512; y*=z;
i steht für
unsigned int i
, wielong i
steht fürlong int i
.int
ist implizit in solchen Kontexten. Wie bei deinem Beispiely*=z
wird interpretiert alsy = (short) ((int) y * (int) z)
, die darauf hinauslaufeny = (short) 261632
. Beachten Sie, dass in diesem Fall keine überlauf bei arithmetischen Auswertungen (die passen inint
sehr gut), aber es gibt einen überlauf während der Konvertierung zurück zushort
. Das Verhalten in diesem Fall ist von der Implementierung abhängig.Ich Frage mich, wie viel der realen Welt Vorteil, es zu machen "integer overflow" unconstrained UB anstatt zu sagen, dass die Compiler können zusätzliche Präzision bei Berechnungen mit integer-Typen, kann beliebig umschreiben oder alles überschüssige-precision-bits jeder Zeit, die Sie nicht alle einverstanden sind mit der Vorzeichen-bit und können in Ihrer Freizeit die Speicherung zusätzliche Präzision in non-volatile integer-Variablen? Solche Regeln erlauben würde, einen compiler zu betrachten
i+1 > i
als unbedingt wahr ist, aber Sie würde nicht zulassen, dass Compiler zu negieren Kausalität. Wie viel Vorteil ist, dass wir darüber hinaus?InformationsquelleAutor AnT
Stellen Sie sich vor Sie haben einen Datentyp, der nur 3 bit breit. Dies ermöglicht Ihnen, zu vertreten, 8 verschiedene Werte, von 0 bis 7. Wenn Sie fügen Sie 1 bis 7, Sie "wrap-around" auf 0 zurück, weil Sie nicht genug bits zum repräsentieren der Wert 8 (1000).
Dieses Verhalten ist gut definiert, für die unsigned-Typen. Es ist nicht gut definiert für signed-Typen, denn es gibt mehrere Methoden für die Darstellung vorzeichenbehaftete Werte, und das Ergebnis ein überlauf wird unterschiedlich interpretiert basierend auf dieser Methode.
Sign-magnitude: das oberste bit stellt das Vorzeichen; 0 für positiv, 1 für negativ. Wenn mein Typ ist drei bit Breite wieder, dann kann ich vertreten, unterzeichnet Werte wie folgt:
Da ein bit für das Vorzeichen, ich habe nur zwei bits zu Kodieren einen Wert von 0 bis 3. Wenn ich 1 zu 3, ich werde überlauf mit -0 als Ergebnis. Ja, es gibt zwei Darstellungen für 0, eine positive und eine negative. Sie nicht begegnen, sign-magnitude-Darstellung oft.
Einer-Komplement: der negative Wert der bitweisen Umkehrung des positiven Wert. Wieder mit der drei-bit-Typ:
Habe ich drei bits zu Kodieren, meine Werte, aber die Strecke ist [-3, 3]. Wenn ich 1 zu 3, ich werde überlauf mit -3 als Ergebnis. Dies unterscheidet sich von der sign-magnitude Ergebnis vor. Wieder gibt es zwei Kodierungen für 0 mit dieser Methode.
Zweier-Komplement: der negative Wert ist das bitweise inverse der positiv-Wert plus 1. In der drei-bit-system:
Wenn ich 1 zu 3, ich werde überlauf mit -4 als Ergebnis, welches sich von den vorherigen zwei Methoden. Beachten Sie, dass wir haben einen etwas größeren Wertebereich [-4, 3] und nur eine Darstellung für 0.
Zweierkomplement ist wahrscheinlich die häufigste Methode der Darstellung signiert Werte, aber es ist nicht der einzige, daher auch der C-standard kann nicht garantieren, was passieren wird, wenn Sie überlaufen-eine vorzeichenbehaftete Ganzzahl-Typ. So hinterlässt das Verhalten undefined, damit der compiler nicht zu tun haben mit der Interpretation mehrerer Darstellungen.
InformationsquelleAutor John Bode
Den Undefiniertes Verhalten kommt vom frühen Portabilität Probleme bei der Ganzzahl-Typen dargestellt werden können, entweder als Zeichen & Größe, Einerkomplement oder Zweierkomplement.
Heutzutage, die alle Architekturen darstellen ganze zahlen als Zweierkomplement, die wrap-around. Aber Vorsicht : seit dem compiler ist Recht davon ausgehen, dass Sie nicht ausgeführt werden kann Undefiniertes Verhalten, könnten Sie auf seltsame Fehler, wenn die Optimierung eingeschaltet ist.
Nein. Auch wenn die zugrunde liegende hardware hat einige intrinsische Verhalten, wie überläufe behandelt werden oder welche Art von Verpackung Auftritt, wird die C-Implementierung ist nicht erforderlich, es zu benutzen. Der C-standard sagt, dass das Verhalten bei signed integer overflow nicht definiert ist. Dies bedeutet, dass die C-Implementierung optimieren von code, ohne Rücksicht auf das, was passiert, wenn der überlauf. Dies kann zu Verhaltensweisen, die auftreten, als wenn die Werte gewickelt werden, oder es kann zu Verhaltensweisen auftreten, wie wenn ein trap aufgetreten ist, oder es kann zu anderen Werten als Verpackung produzieren könnte.
InformationsquelleAutor diapir
In einem signed 8-bit integer, der intuitiven definition von wrap-around Aussehen könnte, gehen von +127 bis -128 -- in Zweierkomplement-Binär: 0111111 (127) und 1000000 (-128). Wie Sie sehen können, das ist der Natürliche Fortschritt der Erhöhung der binären Daten-ohne Berücksichtigung es zur Darstellung einer Ganzzahl mit oder ohne Vorzeichen. Counter-intuitiv, das eigentliche überlauf stattfindet, wenn Sie sich von -1 (11111111) 0 (00000000) in der unsigned-integer im Sinne der wrap-around.
Dies beantwortet nicht die tiefere Frage, was das richtige Verhalten ist, wenn eine vorzeichenbehaftete integer-overflows, weil es keine "richtige" Verhalten nach dem standard.
InformationsquelleAutor Nathan L