Używam wszędzie niepodpisanych int i nie jestem pewien, czy powinienem. Może to być od kolumny identyfikatora klucza podstawowego bazy danych do liczników itp. Jeśli liczba nigdy nie powinna być ujemna, zawsze będę używał znaku int bez znaku.
Jednak zauważam z kodu innego, że nikt inny tego nie robi. Czy przeoczyłem coś kluczowego?
Edycja: Odkąd to pytanie zauważyłem również, że w C zwracanie ujemnych wartości błędów jest powszechne, a nie zgłaszanie wyjątków jak w C ++.
c++
c
programming-practices
wting
źródło
źródło
for(unsigned int n = 10; n >= 0; n --)
(pętle nieskończenie)Odpowiedzi:
Gdy obliczenia obejmują zarówno podpisane, jak i niepodpisane typy, a także różne rozmiary, reguły promocji typów mogą być złożone i prowadzić do nieoczekiwanego zachowania .
Uważam, że jest to główny powód, dla którego Java pominęła niepodpisane typy int.
źródło
int
nie stanowiłyby jednak takiej trudności (ponieważ wszelkie obliczenia będą się promowaćint
); Nie mam nic dobrego do powiedzenia na temat braku typu bajtu bez znaku.Myślę, że Michael ma rację, ale IMO powoduje, że wszyscy używają int cały czas (szczególnie w
for (int i = 0; i < max, i++
), ponieważ nauczyliśmy się tego w ten sposób. Kiedy każdy przykład w książce „ jak się uczyć programowania ” używaint
wfor
pętli, bardzo niewielu kiedykolwiek kwestionuje tę praktykę.Innym powodem jest to, że
int
jest o 25% krótszyuint
i wszyscy jesteśmy leniwi ... ;-)źródło
++
podczas zwiększania, pomimo tego, że jego szczególne zachowanie jest rzadko potrzebne i może nawet prowadzić do bezcelowego odrzucania kopii, jeśli indeks pętli jest iteratorem lub innym nie fundamentalnym typem (lub kompilator jest naprawdę gęsty) .Kodowanie informacji o zakresie na typy jest dobrą rzeczą. Wymusza używanie rozsądnych liczb w czasie kompilacji.
Wydaje się, że wiele architektur ma wyspecjalizowane instrukcje postępowania z
int
->float
konwersjami. Konwersja zunsigned
może być wolniejsza (trochę) .źródło
Mieszanie typów podpisanych i niepodpisanych może wprowadzić Cię w świat bólu. I nie możesz używać wszystkich niepodpisanych typów, ponieważ napotkasz rzeczy, które albo mają prawidłowy zakres, który zawiera liczby ujemne, albo potrzebują wartości wskazującej błąd, a -1 jest najbardziej naturalne. Tak więc wynik netto jest taki, że wielu programistów używa wszystkich typów całkowitych ze znakiem.
źródło
Dla mnie typy dotyczą komunikacji. Używając jawnie int bez znaku mówisz mi, że podpisane wartości nie są prawidłowymi wartościami. To pozwala mi dodać pewne informacje podczas odczytywania kodu oprócz nazwy zmiennej. Idealnie byłbym typem anonimowym, który powiedziałby mi więcej, ale daje mi więcej informacji niż gdybyś używał ints wszędzie.
Niestety nie wszyscy są bardzo świadomi tego, co komunikuje ich kod, i prawdopodobnie jest to powód, dla którego wszędzie widzisz ints, nawet jeśli wartości są przynajmniej niepodpisane.
źródło
Używam
unsigned int
w C ++ głównie dla indeksów tablicowych i dla każdego licznika rozpoczynającego się od 0. Myślę, że dobrze jest powiedzieć wprost: „ta zmienna nie może być ujemna”.źródło
Powinieneś się tym przejmować, gdy masz do czynienia z liczbą całkowitą, która może faktycznie zbliżyć się lub przekroczyć granice podpisanej liczby całkowitej. Ponieważ dodatnia wartość maksymalna 32-bitowej liczby całkowitej wynosi 2 147 483 647, powinieneś użyć int bez znaku, jeśli wiesz, że to a) nigdy nie będzie ujemne, a b) może osiągnąć 2 147 483 648. W większości przypadków, w tym kluczy bazy danych i liczników, nigdy nawet nie podchodzę do tego rodzaju liczb, więc nie zawracam sobie głowy martwieniem się, czy bit znaku jest używany dla wartości liczbowej, czy też do wskazania znaku.
Powiedziałbym: użyj int, chyba że wiesz, że potrzebujesz int bez znaku.
źródło
Jest to kompromis między prostotą a niezawodnością. Im więcej błędów można wykryć w czasie kompilacji, tym bardziej niezawodne jest oprogramowanie. Różni ludzie i organizacje zajmują różne punkty w tym spektrum.
Jeśli kiedykolwiek będziesz programował w Adzie o wysokiej niezawodności, użyjesz nawet różnych typów dla zmiennych, takich jak odległość w stopach vs. odległość w metrach, a kompilator oznaczy go, jeśli przypadkowo przypiszesz jeden do drugiego. Jest to idealne rozwiązanie do programowania pocisku kierowanego, ale przesadzanie (gra słów), jeśli sprawdzasz poprawność formularza internetowego. W obu przypadkach nie musi być nic złego, o ile spełnia ono wymagania.
źródło
Jestem skłonny zgodzić się z rozumowaniem Joela Ethertona, ale doszedłem do przeciwnego wniosku. Z mojego punktu widzenia, nawet jeśli wiesz, że jest mało prawdopodobne, aby liczby kiedykolwiek zbliżyły się do limitów podpisanego typu, jeśli wiesz, że liczby ujemne się nie zdarzą, to jest bardzo mało powodu, aby używać podpisanego wariantu typu.
Z tego samego powodu, dla którego w kilku wybranych przypadkach użyłem
BIGINT
(64-bitowej liczby całkowitej) zamiastINTEGER
(32-bitowej liczby całkowitej) w tabelach programu SQL Server. Prawdopodobieństwo, że dane osiągną limit 32-bitowy w rozsądnym czasie, jest niewielkie, ale jeśli tak się stanie, konsekwencje w niektórych sytuacjach mogą być dość katastrofalne. Pamiętaj tylko, aby poprawnie mapować typy między językami, w przeciwnym razie skończysz z ciekawą dziwnością naprawdę daleko w dół drogi ...To powiedziawszy, dla niektórych rzeczy, takich jak wartości klucza podstawowego bazy danych, podpisane lub niepodpisane, tak naprawdę nie ma znaczenia, ponieważ dopóki nie naprawisz ręcznie uszkodzonych danych lub czegoś podobnego, nigdy nie będziesz miał do czynienia z wartością bezpośrednio; to identyfikator, nic więcej. W takich przypadkach spójność jest prawdopodobnie ważniejsza niż dokładny wybór podpisu. W przeciwnym razie powstają kolumny z kluczem obcym, które są podpisane, i inne, które są niepodpisane, bez widocznego wzorca - lub znowu ta interesująca dziwność.
źródło
Zalecałbym, aby poza kontekstami przechowywania danych i wymiany danych ograniczonymi przestrzenią, ogólnie rzecz biorąc, należy używać podpisanych typów. W większości przypadków, gdy 32-bitowa liczba całkowita ze znakiem byłaby zbyt mała, ale 32-bitowa wartość bez znaku wystarczyłaby na dziś, nie potrwa długo, zanim 32-bitowa wartość bez znaku też nie będzie wystarczająco duża.
Podstawowymi czasami, w których należy używać typów bez znaku, są sytuacje, gdy albo łączy się wiele wartości w większą (np. Konwertuje cztery bajty na liczbę 32-bitową), albo rozkłada większe wartości na mniejsze (np. Przechowujemy liczbę 32-bitową jako cztery bajty ) lub gdy ma się pewną ilość, która ma się okresowo „przewracać” i trzeba sobie z tym poradzić (pomyśl o mierniku użyteczności publicznej; większość z nich ma wystarczającą liczbę cyfr, aby zapewnić, że nie przewrócą się między odczytami jeśli są czytane trzy razy w roku, ale nie na tyle, aby nie przewróciły się w okresie użytkowania miernika). Typy niepodpisane często mają wystarczającą „dziwność”, dlatego należy ich używać tylko w przypadkach, w których ich semantyka jest konieczna.
źródło
size_t
jest niepodpisany iptrdiff_t
podpisany.Używam niepodpisanych ints, aby mój kod i jego intencje były bardziej przejrzyste. Jedną rzeczą, którą robię, aby uchronić się przed nieoczekiwanymi niejawnymi konwersjami podczas wykonywania arytmetyki zarówno z typami podpisanymi, jak i niepodpisanymi, jest użycie niepodpisanego skrótu (zwykle 2 bajty) dla moich niepodpisanych zmiennych. Jest to skuteczne z kilku powodów:
Ogólna zasada jest taka, że typ zmiennych bez znaku powinien mieć niższą rangę niż typ zmiennych ze znakiem, aby zapewnić awans do typu ze znakiem. Wtedy nie będziesz mieć żadnych nieoczekiwanych zachowań związanych z przepełnieniem. Oczywiście nie możesz tego zapewnić przez cały czas, ale (najczęściej) jest to możliwe.
Na przykład ostatnio miałem dla pętli coś takiego:
Dosłowne „2” jest typu int. Gdybym był liczbą całkowitą bez znaku zamiast skrótu bez znaku, wówczas w podwyrażeniu (i-2) 2 byłoby promowane do postaci bez znaku (ponieważ int ma wyższy priorytet niż znak int). Jeśli i = 0, to podwyrażenie jest równe (0u-2u) = pewna ogromna wartość z powodu przepełnienia. Ten sam pomysł z i = 1. Jednakże, ponieważ i jest skrótem bez znaku, jest promowany do tego samego typu, co literał „2”, który jest podpisany int i wszystko działa dobrze.
Dla większego bezpieczeństwa: w rzadkim przypadku, gdy implementowana architektura powoduje, że int ma 2 bajty, może to spowodować, że oba operandy w wyrażeniu arytmetycznym zostaną awansowane na int bez znaku w przypadku, gdy krótka zmienna bez znaku nie pasuje w podpisany 2-bajtowy int, którego ostatni ma maksymalną wartość 32 767 <65 535. (Zobacz https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned, aby uzyskać więcej informacji). Aby temu zapobiec, możesz po prostu dodać static_assert do swojego programu w następujący sposób:
i nie będzie się kompilował na architekturach, gdzie int ma 2 bajty.
źródło