2016-07-31 37 views
5

Próbowałem scanf("%u",&number) i wprowadziłem liczbę ujemną problem jest, gdy I printf("%d",number) Otrzymuję liczbę ujemną. Myślałem, że to uniemożliwi mi odczytanie liczby ujemnej. Czy scanf("%d",&number) i scanf("%u",&number) to samo? lub jest to tylko do odczytu.scanf% u liczba ujemna?

Czy robię coś, co nazywa się niezdefiniowanym zachowaniem, więc?

EDIT:

Od Wikipedia czytam to:

% u: Skanowanie do dziesiętnych unsigned int (zauważ, że w standardzie C99 wejście wartość minus jest opcjonalne, więc jeśli minus znak jest odczytywany, żadnych błędy powstaną, a wynik będzie dwóch za dopełnienie liczbę ujemną, prawdopodobnie bardzo dużą wartość.

Jest to nieco mylące czytanie odpowiedzi na WJ i powyżej. Czy ktoś może to wyjaśnić?

+1

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

+2

http://stackoverflow.com/questions/5208641/różnica między drukowaniem-pamięci-adresu-używania-u-i-d-w-c Zobacz ten link. Powinien odpowiedzieć na twoje pytanie. – Module

+0

@BlackBird Dokładny czas haha ​​ – Module

Odpowiedz

2

Tak, to niezdefiniowane zachowanie, tak czy inaczej.

Zważywszy zmiennej number jest typu unsigned, %d w printf() oczekuje argumentu signed int typu przepuszczanie typu unsigned jest UB.

OTOH, jeśli number jest typu podpisanego, przy skanowaniu jest UB na pierwszym miejscu, przy użyciu %u.

Jak można się było spodziewać

[...] zapobiec mnie od czytania liczba ujemna

formatu specyfikatory nie tam zapobiec niewłaściwe wejście. Jeśli specyfikator formatu nie jest zgodny z podanym argumentem, wywołuje on undefined behavior.

Cytowanie C11, załącznik J.2 scenariusze wywołującej UB

Wynikiem przekształcenia jednego z sformatowanych funkcji wejściowych nie da się przedstawiony w odpowiednim obiektem, lub obiekt odbiorczy nie an odpowiedni typ

+0

'printf ("% u ", - 1)' czy to także UB? – rondino

+1

@rondino technicznie, to jest. [zobacz to] (http://stackoverflow.com/q/4664100/2173917) –

+0

niektórzy ludzie mówią Tak, inni mówią Nie:/czytając odpowiedzi! – rondino

1

Jak wyjaśniono szczegółowo Sourav Ghosh, przy użyciu formatów, które są niezgodne z rzeczywistymi typów przekazywanych jest potencjalnym problemem. Jednak w tym konkretnym przypadku, na obecnych architekturach komputerów PC, nie jest to tak naprawdę problem, ponieważ ani int ani reprezentacje pułapek.

Możesz zeskanować liczbę ujemną za pomocą scanf("%u", &number);.Zostanie on zanegowany w typie docelowym, to jest unsigned int, z tą samą reprezentacją bitową, co liczba ujemna w podpisanej int, dla reprezentacji uzupełnienia dwóch, która jest prawie uniwersalna w obecnych architekturach.

scanf przekształca %u dopasowując ewentualnie podpisany liczba całkowita, których format jest taki sam, jak oczekiwano dla sekwencji badanej funkcji strtoul o wartości 10 argumentowego bazowej. Odpowiednim argumentem będzie wskaźnik do liczby całkowitej bez znaku.

W strtol, strtoll, strtoul i strtoull funkcje konwersji początkowa część łańcucha wskazywanego przez nptr do long int, long long int, unsigned long int i unsigned long long int reprezentacji, odpowiednio. Najpierw rozkładają łańcuch wejściowy na trzy części: początkową, możliwie pustą sekwencję znaków białych znaków (zgodnie z funkcją isspace), sekwencję tematyczną przypominającą liczbę całkowitą reprezentowaną w niektórych podstawkach wyznaczoną przez wartość podstawy, oraz końcowy ciąg jednego lub więcej nierozpoznanych znaków, w tym kończący znak null wejściowego ciągu znaków. Następnie próbują przekonwertować sekwencję tematyczną na liczbę całkowitą i zwracają wynik.

Jeśli wartość podstawy wynosi od 2 do 36 (włącznie), oczekiwana forma sekwencji tematycznej to ciąg liter i cyfr reprezentujących liczbę całkowitą z podstawnikiem, opcjonalnie poprzedzony znakiem plus lub minus , ale bez uwzględnienia przyrostka całkowitego.

... Jeśli sekwencja tematu ma oczekiwany kształt, a wartość podstawy wynosi od 2 do 36, jest używana jako podstawa do konwersji, przypisując każdej literze jej wartość podaną powyżej. Jeśli sekwencja tematyczna zaczyna się od znaku minus, wartość wynikająca z konwersji jest zanegowana (w typie zwracanym).

Jeżeli rodzaj number jest unsigned int zachowanie określa się i wartość ujemna jest analizowany i przechowywane w number stosując unsigned semantykę negacji. Drukowanie tę wartość z printf("%d", number); jest na najlepszej realizacji zdefiniowanego, ale znowu na obecnych architektur komputerowych, wypisze liczbę ujemną, który pierwotnie był analizowany przez scanf("%u", &number);

Wniosek: chociaż wydaje się nieszkodliwe, to jest bardzo niechlujny używać int i unsigned int zamiennie i używać niewłaściwych formatów w printf i scanf. W rzeczywistości mieszanie typów podpisanych i niepodpisanych w wyrażeniach, zwł. w porównaniach jest bardzo podatny na błędy, ponieważ semantyka C dla takich konstrukcji czasami jest sprzeczna z intuicją.

+0

"* Zostanie zanegowane w typie docelowym, o nazwie" unsigned ", z tą samą reprezentacją bitową, co liczba ujemna w' signed int'. * "- To prawda tylko dla reprezentacji uzupełnienia 2-s (która jest prawie uniwersalna ale nie gwarantowane). –

+0

@KeithThompson: poprawne. Zaktualizowałem odpowiedź. Nie mogę się doczekać tych przestarzałych możliwości, które zostaną usunięte z przyszłej wersji standardu C. – chqrlie