Co to jest uint_fast32_t i dlaczego należy go używać zamiast zwykłych int i uint32_t?

110

Tak więc powodem typedef: ed prymitywne typy danych jest abstrakcja reprezentacji niskiego poziomu i ułatwienie zrozumienia (uint64_t zamiast long longtypu, który ma 8 bajtów).

Jednak jest to, uint_fast32_tco ma to samo typedefco uint32_t. Czy użycie „szybkiej” wersji przyspieszy program?

Amumu
źródło
long long może nie być 8 bajtów, możliwe jest posiadanie long long z 1 bajtem (w przypadku gdy CHAR_BIT ma co najmniej 64) lub 3738383 bajtów. również uint64_t może mieć 1, 2, 4 lub 8 bajtów, CHAR_BIT musi mieć do tego 64, 3, 16 lub 8.
12431234123412341234123

Odpowiedzi:

135
  • intna niektórych platformach może mieć nawet 16 bitów. To może być niewystarczające dla Twojej aplikacji.
  • uint32_tnie ma gwarancji, że będzie istnieć. Jest to opcjonalne, typedefktóre implementacja musi zapewnić, jeśli ma typ liczby całkowitej bez znaku równej dokładnie 32-bitom. Niektóre mają na przykład 9-bitowe bajty, więc nie mają rozszerzenia uint32_t.
  • uint_fast32_tjasno określa twój zamiar: jest to typ co najmniej 32 bitów, który jest najlepszy z punktu widzenia wydajności. uint_fast32_tw rzeczywistości może mieć długość 64 bitów. To zależy od wdrożenia.

... jest uint_fast32_ttaki sam typ, jak uint32_t...

To, na co patrzysz, nie jest standardem. To szczególna implementacja (BlackBerry). Więc nie możesz stąd wywnioskować, że uint_fast32_tjest to zawsze to samo, co uint32_t.

Zobacz też:

Yakov Galka
źródło
36
Dobra odpowiedź. Dla kompletności można by również wskazać różnicę uint_least32_t, która jest taka sama, uint_fast32_tz wyjątkiem tego, że preferuje mniejszy magazyn niż szybkość.
Damon,
2
Dlaczego najszybsza liczba całkowita o szerokości co najmniej 32-bitowej miałaby być większa niż 32-bitowa? Zawsze myślałem, że jeśli jest mniej bitów, będzie mniej bitów, nad którymi procesor musi pracować, a więc szybciej. Czego tu brakuje?
Shane Hsu,
12
@ShaneHsu: powiedzmy, że 64-bitowy procesor będzie miał 64-bitowe lato, które sumuje 64-bitowe liczby w jednym cyklu. Nie ma znaczenia, czy wszystko, co chcesz zrobić, to pracować na liczbach 32-bitowych, nie będzie to szybsze niż jeden cykl. Teraz, chociaż tak nie jest w przypadku x86 / amd64, 32-bitowe liczby całkowite mogą nawet nie być adresowalne. W takim przypadku praca nad nimi wymaga dodatkowych operacji w celu wyodrębnienia 32-bitowych z, powiedzmy, 64-bitowych jednostek wyrównanych. Zobacz także powiązane pytanie. Standard C ++ jest napisany tak, aby mógł działać na maszynie, która ma 37-bitowe słowa ... więc w ogóle nie ma tam typu 32-bitowego.
Yakov Galka
42

Różnica polega na ich dokładności i dostępności.

Doc tutaj mówi:

unsigned całkowitą o szerokości dokładnie 8, 16, 32 i 64 bitów, odpowiednio, ( pod warunkiem, tylko wtedy, gdy realizacja bezpośrednio podtrzymuje typu )

uint8_t
uint16_t
uint32_t
uint64_t

I

najszybszy typ liczby całkowitej bez znaku bez znaku o szerokości odpowiednio co najmniej 8, 16, 32 i 64 bitów

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

Różnica jest więc dość wyraźna, że uint32_tjest to typ, który ma dokładnie 32 bity, a implementacja powinna zapewnić go tylko wtedy, gdy ma typ z dokładnie 32 bitami, a następnie może wpisać ten typ jako uint32_t. Oznacza to, uint32_tże może być dostępny lub nie .

Z drugiej strony uint_fast32_tjest to typ, który ma co najmniej 32 bity, co również oznacza, że ​​implementacja może być zdefiniowana uint32_ttak, uint_fast32_t jakby zapewniała uint32_t. Jeśli nie dostarcza uint32_t, to uint_fast32_tmoże to być typedef dowolnego typu, który ma co najmniej 32bity.

Nawaz
źródło
3
Ale jaki jest powód, dla którego na przykład uint_fast32_t jest szybszy niż uint32_t? Dlaczego jest szybszy?
Destructor
2
@PravasiMeet: Nie wszystkie liczby całkowite dostępne w ten sam sposób. Dostęp do niektórych jest łatwiejszy niż do innych. Łatwiej oznacza mniej obliczeń, bardziej bezpośredni, co skutkuje szybszym dostępem. Teraz uint32_tjest dokładnie 32-bitowy we wszystkich systemach (jeśli istnieje), co może nie być szybsze w porównaniu z, powiedzmy, 64-bitowym. uint_fast32_tz drugiej strony co najmniej 32-bitowy, może być nawet 64-bitowy.
Nawaz
10
@Destructor: Na niektórych procesorach, jeśli zmienna zostanie zapisana w rejestrze, który jest dłuższy, kompilator może być zmuszony do dodania dodatkowego kodu, aby odciąć dodatkowe bity. Na przykład, jeśli uint16_t x;zostanie zapisany w 32-bitowym rejestrze w ARM7-TDMI, kod x++;może wymagać oceny jako x=((x+1)<<16)>>16);. W kompilatorach dla tej platformy uint_fast16_tnajprawdopodobniej zostanie zdefiniowany jako synonim, uint32_taby tego uniknąć.
supercat
dlaczego [u]int_(fast|least)N_tnie są również opcjonalne? Z pewnością nie wszystkie architektury są wymagane przez standard do obsługi pierwotnych typów co najmniej 64-bitowych? Jednak sformułowanie stdint.hsugeruje, że muszą. Wydaje mi się dziwne, że egzekwujemy to od 1999 r., Kilka lat przed tym, jak 64-bitowe komputery stały się głównym nurtem - nie mówiąc już o opóźnieniu w stosunku do (w wielu przypadkach wciąż aktualnych) architektur wbudowanych. To wydaje mi się dużym niedopatrzeniem.
underscore_d
1
@underscore_d: Nie ma szczególnego powodu, na przykład, dla którego standard nie miałby zastosowania do implementacji PIC12 z 16 bajtami pamięci RAM na dane i miejscem na 256 instrukcji. Taka implementacja musiałaby odrzucić wiele programów, ale to nie powinno uniemożliwić jej zachowywania się w określony sposób dla programów, których potrzeby mogłaby zaspokoić.
supercat
4

Kiedy jesteś #include inttypes.hw swoim programie, masz dostęp do wielu różnych sposobów przedstawiania liczb całkowitych.

Typ uint_fast * _t po prostu definiuje najszybszy typ reprezentujący daną liczbę bitów.

Pomyśl o tym w ten sposób: definiujesz zmienną typu shorti używasz jej kilka razy w programie, co jest całkowicie poprawne. Jednak system, nad którym pracujesz, może działać szybciej z wartościami typu int. Definiując zmienną jako typ uint_fast*t, komputer po prostu wybiera najbardziej wydajną reprezentację, z jaką może pracować.

Jeśli nie ma różnicy między tymi reprezentacjami, system wybiera dowolną z nich i używa jej konsekwentnie przez cały czas.

Harley Sugarman
źródło
9
Dlaczego inttypes.h, a nie stdint.h? Wygląda na to, że inttypes.h zawiera tylko różne lekko przydatne puch, a także zawiera stdint.h?
Lundin,
@underscore_d Znam różnicę. Ale kto używa stdio.h w profesjonalnych programach, niezależnie od obszaru zastosowania?
Lundin
@Lundin Nie mam pojęcia, kim oni są ani czy istnieją! Pomyślałem, że przydatne może być udostępnienie linku opisującego, czym jest ten „lekko przydatny puch” ;-) Może to pomoże ludziom zdać sobie sprawę, że masz rację, a oni tego nie potrzebują.
underscore_d
-1

Zwróć uwagę, że szybka wersja może być większa niż 32 bity. Podczas gdy szybki int będzie ładnie pasował do rejestru i zostanie wyrównany i tym podobne, ale zużyje więcej pamięci. Jeśli masz duże tablice tych tablic, twój program będzie wolniejszy z powodu większej liczby trafień w pamięci podręcznej i przepustowości.

Nie sądzę, aby nowoczesny CPUS skorzystał na fast_int32, ponieważ generalnie znak rozszerzający się z 32 do 64 bitów może wystąpić podczas instrukcji ładowania, a pomysł, że istnieje „natywny” format liczb całkowitych, który jest szybszy, jest staroświecki.

Gil Colgate
źródło