2016-07-06 3 views
3

Können Sie mir erklären, wie Überläufe und Unterläufe für signed char und unsigned char funktioniert?Überläufe und Unterläufe in C Sprache

int main() { 
    signed char c; 

    scanf("%d",&c); 
    printf("%d\n",c); 
    printf("%c\n",c); 

return 0; 
} 

In diesem Fall, wenn dank scanf, habe ich c=200 gibt es einen Überlauf und dies durch die ersten printf zeigt ist. Die zweite printf gibt mir das gleiche ASCII-Zeichen von 200 ...
Warum?

+9

'scanf ("% d ", & c)' ist kein Überlauf oder Unterlauf; Es ist Undefined Behavior, Punkt. – aschepler

+0

Um @ascheppler weiter zu vervollständigen, ist das wahrscheinlichste Ergebnis, 3 weitere Bytes nach der c-Variablen zu verdecken, vielleicht sogar mit der Rücksprungadresse selbst zu verwirren. Angenommen, der Compiler (Optimierer) verkraftet nichts und verhält sich ähnlich wie die manuelle intuitive Übersetzung. –

Antwort

6

scanf 's %d erwartet eine int, also gibt es nichts anderes undefiniertes Verhalten.
Sie sollten dies tun:

int d; 
scanf("%d", &d); 
whatevertype c = (whatevertype)d; 

jedoch Integer-Überlauf unterzeichnet nicht definiert ist. Aber wenn Sie nicht signierte Typen verwenden, wie

unsigned char c = (unsigned char)d; 

Dann wird c garantiert d Modul 2 auf die Potenz der Anzahl von Bits in einem unsigned char sein.

+0

@chux: Geändert, Sie sind korrekt – Dani

+0

können Sie mir erklären, was ist ein undefiniertes Verhalten und was ist der Unterschied zwischen Überläufen? – bigguy

+0

@bigguy: Sie können es sich hier ansehen: https://en.wikipedia.org/wiki/Undefined_behavior oder hier http://Stackoverflow.com/a/18420754/694576 oder hier https://www.google .com/search? q = was + ist + undefined + verhalten – alk

0

Jeder Compiler läuft auf einer bestimmten Maschine, auf einer bestimmten Hardware.

Nehmen wir zum Beispiel an, dass unsere vorzeichenbehaftete Ganzzahl von Maschine/Prozessor im Bereich von 16 Bit liegt. Dies bedeutet, dass MAX_INT der Hexadezimalwert 0x7fff ist, der 32767 Dezimalwert ist und MIN_INT 0x8000 Hexadezimalwert ist, was -32768 Dezimalwert ist.

Die meisten Maschinen haben ein ALU-Steuerregister, das definiert, wie sich vorzeichenbehaftete Ganzzahlen im Falle eines Überlaufs verhalten. Dieses Register hat im Allgemeinen ein Sättigungsflag.

Überlauf Beispiel: Wenn die Sättigungs Flag gesetzt ist, als im Fall, dass das Ergebnis der letzten ganze Zahl ALU-Operation signiert größer als MAX_INT ist, wird das Ergebnis auf MAX_INT eingestellt wird. zum Beispiel, wenn die letzte Operation 0x7ffe zu 0x2 hinzugefügt hat, wird das Ergebnis 0x7fff sein.

Wenn das Sättigungsflag nicht gesetzt ist, wird das Ergebnis wahrscheinlich auf die unteren 16 Bits des korrekten Ergebnisses gesetzt, wenn das Ergebnis der letzten ALU-Operation mit Vorzeichen mit Vorzeichen größer als MAX_INT ist. In unserem Fall 0x7ffe + 0x2 = 0x8000, was die kleinste ganze Zahl ist.

Bei Integer ohne Vorzeichen der Compiler Garantien, dass das Ergebnis nach der Definition von unsigned int zusätzlich in C.

Unterschreitung Beispiel wird: Jede Maschine hat MIN_FLOAT Definition. Und wenn das Sättigungs-Flag gesetzt ist, wird ein Ergebnis, das kleiner als MIN_FLOAT ist, auf MIN_FLOAT gerundet. Sonst wird das Ergebnis dem Betrieb des Prozessors entsprechen. (Suchen Sie im Internet nach den Begriffen Mantisse und Exponent, wenn Sie Interesse an Fließkommadarstellungen und Operationen haben).

0

Der Grund, warum Sie in der ersten printf-Anweisung einen Überlauf erhalten, liegt daran, dass Sie das Zeichen als signiertes Zeichen definiert haben und wenn Sie sie in einem% d-Format ausgeben, das ganzzahlig ist. Sie erhalten einen Bereich von 0- 127 und -1 bis -128 weil wir alle wissen, verbrauchen char ein Byte im Speicher und indem Sie sie als Zeichen mit Vorzeichen teilen Sie sie in positiven und negativen Werten in einfachen Worten ein vorzeichenloses Byte reicht von 0 bis 255 und soo ein signiertes Zeichen gibt Ihnen sowohl positive als auch negative Werte von 0-127 und -1 bis -128.

+0

hey @bigguy Wenn du die Antwort hilfreich findest, vergiss nicht das zu markieren:) – dreamBegin