2016-07-31 21 views
5

Ich habe versucht scanf("%u",&number) und ich habe negative Nummer eingegeben das Problem ist, wenn ich printf("%d",number) bekomme ich die negative Zahl. Ich dachte, das würde mich davon abhalten, negative Zahlen zu lesen. Sind scanf("%d",&number) und scanf("%u",&number) die gleiche Sache wirklich? oder ist es nur für die Lesbarkeit.scanf% u negative Zahl?

Mache ich etwas so genanntes undefiniertes Verhalten?

EDIT:

Von Wikipedia Ich lese diese:

% u: für dezimal unsigned int Scan (Beachten Sie, dass in der Standard-C99 die Eingangswert minus Zeichen optional ist, wenn also ein Minus Zeichen gelesen wird, werden keine Fehler auftreten und das Ergebnis wird das Zweierkomplement einer negative Zahl, wahrscheinlich ein sehr großer Wert sein.

Es ist ein wenig verwirrend, SO Antworten und darüber zu lesen. Kann jemand es klarer machen?

+1

http://stackoverflow.com/questions/5208641/difference-between-printing-a-memory-address-using-u-and-d-in-c –

+2

http://stackoverflow.com/questions/5208641/Unterschied-zwischen-Drucken-eine-Speicher-Adresse-Using-U-und-D-in-c Werfen Sie einen Blick auf diesen Link. Es sollte deine Frage beantworten. – Module

+0

@BlackBird Genaues Timing haha ​​ – Module

Antwort

2

Ja, es ist undefiniertes Verhalten, egal wie.

Anbetracht variable number ist vom Typ unsigned, %d in printf() ein Argument des Typs signed int erwartet, Hindurchleiten eines unsigned Typ UB wird.

OTOH, wenn number ist signiert Typ, mit %u zum Scannen ist UB an erster Stelle.

Wie Sie erwartet haben könnte

[...] verhindern, dass ich aus der Lektüre negative Zahl

Formatbezeichner sind nicht dort falsche Eingabe zu verhindern. Wenn der Formatbezeichner nicht mit dem angegebenen Argument übereinstimmt, wird undefined behavior aufgerufen.

Zitiert C11, Anhang J.2, Szenarien UB Aufruf

Das Ergebnis einer Umwandlung von einer der formatierten Eingabefunktionen können nicht werden in dem entsprechenden Objekt dargestellt wird, oder das empfangende Objekt keinen ein geeigneter Typ

+0

'printf ("% u ", - 1)' ist es auch UB? – rondino

+1

@rondino technisch ist es. [sieh dies] (http://stackoverflow.com/q/4664100/2173917) –

+0

einige Leute sagen, dass andere sagen Nein:/Lesen der Antworten! – rondino

1

Wie im Detail durch Sourav Ghosh, Formate verwenden, die mit den tatsächlichen Typen inkonsistent sind vergangen ist ein mögliches Problem. Für diesen speziellen Fall ist dies jedoch bei aktuellen PC-Architekturen kein wirkliches Problem, da weder int noch unsigned int Trap-Repräsentationen aufweisen.

Sie können eine negative Nummer mit scanf("%u", &number); scannen.Es wird im Zieltyp negiert, nämlich unsigned int, mit der gleichen bitweisen Darstellung wie die negative Zahl in einem vorzeichenbehafteten int, für Zweierkomplement-Darstellung, die auf aktuellen Architekturen fast universell ist.

scanf wandelt %u durch eine gegebenenfalls signierten Dezimalzahl passende, wobei das Format ist das gleiche wie für das Subjekt-Sequenz der strtoul Funktion mit dem Wert 10 für die Basis Argument erwartet. Das entsprechende Argument soll ein Zeiger auf unsigned Integer sein.

Die strtol, strtoll, strtoul und strtoull Funktionen umwandeln der Anfangsteil der Zeichenfolge durch nptr zu long int spitz, long long int, unsigned long int und unsigned long long int Darstellung, respectively. Zuerst zerlegen sie die Eingabezeichenfolge in drei Teile: eine anfängliche, möglicherweise leere Sequenz von Leerzeichen (wie durch die isspace-Funktion spezifiziert), eine Subjektsequenz, die einer Ganzzahl ähnelt, die in einer durch den Wert der Basis bestimmten Radix dargestellt ist, und eine letzte Zeichenfolge aus einem oder mehreren nicht erkannten Zeichen, einschließlich des abschließenden Nullzeichens der Eingabezeichenfolge. Dann versuchen sie, die Subjektsequenz in eine Ganzzahl zu konvertieren und das Ergebnis zurückzugeben.

Wenn der Wert von base zwischen 2 und 36 (einschließlich) ist, ist die erwartete Form der Betreffsequenz eine Folge von Buchstaben und Ziffern, die eine ganze Zahl mit der durch base angegebenen Wurzel darstellen, optional gefolgt von einem Plus- oder Minuszeichen , aber ohne ein ganzzahliges Suffix.

... Wenn die Betreffsequenz die erwartete Form hat und der Wert der Basis zwischen 2 und 36 liegt, wird sie als Basis für die Konvertierung verwendet, wobei jedem Buchstaben der oben angegebene Wert zugewiesen wird. Wenn die Betreffsequenz mit einem Minuszeichen beginnt, wird der aus der Konvertierung resultierende Wert negiert (im Rückgabetyp).

Wenn die Art der numberunsigned int ist, Verhalten definiert, und der negativer Wert wird analysiert und gespeichert in number die unsigned Negation Semantik verwendet wird. Drucken Sie diesen Wert mit printf("%d", number); bester Umsetzung ist definiert, aber auch hier auf aktuellen PC-Architekturen, die negative Zahl drucken, die ursprünglich von scanf("%u", &number);

Fazit analysiert wurde: Obwohl es harmlos scheint, es ist sehr schlampig int und unsigned int zu verwenden austauschbar und die falschen Formate in printf und scanf zu verwenden. In der Tat, Mischen von Typen mit und ohne Vorzeichen in Ausdrücken, esp. in Vergleichen ist sehr fehleranfällig, da die C-Semantik für solche Konstruktionen manchmal kontraintuitiv ist.

+0

"* Es wird im Zieltyp negiert, mit dem Namen' unsigned', mit der gleichen bitweisen Darstellung wie die negative Zahl in einem 'signed int'. * "- Das ist nur für die Zweierkomplement-Darstellung (die fast universell ist) aber nicht garantiert). –

+0

@KeithThompson: richtig. Ich habe die Antwort aktualisiert. Ich kann es kaum erwarten, dass diese veralteten Möglichkeiten aus einer zukünftigen Version des C-Standards entfernt werden. – chqrlie

Verwandte Themen