Dlaczego int ma tylko 2 bajty?

9

Gdy używasz C / C ++ na innych platformach, inttyp wynosi zazwyczaj 4 bajty (lub potencjalnie więcej). Jednak w Arduino to tylko 2 bajty.

Dlaczego jest inaczej? Czy wpływa to na wydajność, jeśli zawsze używam 4 bajtów long?

Peter Bloomfield
źródło
2
zwróć uwagę, że intw Arduino Due są 4 bajty. A shortbędzie 2 bajtami na wszystkich istniejących Ardunios, ale podkreślam porady innych, aby użyć int16_tlub uint16_t.
Ron

Odpowiedzi:

10

ATmega328 stosowany w wielu Arduinos to 8-bitowy mikrokontroler. Oznacza to, że rejestry mają 8 bitów, szyna danych ma 8 bitów, porty to 8 bitów. Istnieje kilka minimalnych 16-bitowych aspektów systemu (np. Jeden z timerów), ale prawie wszystko ma 8 bitów.

Dlatego większość operacji obsługuje jednocześnie 8 bitów. Praca na czymkolwiek oprócz 8-bitowych (tj. 16-bitowych lub 32-bitowych liczb całkowitych i liczb zmiennoprzecinkowych) wymaga tego, co można zasadniczo opisać jako emulacji oprogramowania, gdzie kompilator używa wielu instrukcji do pracy na tych większych zmiennych.

8-bitów jest oczywiście wystarczające do zaadresowania portu 8-bitowego. Wystarczy również poradzić sobie z wieloma licznikami pętli, zwracanymi wartościami i znakami ASCII. Ale to naprawdę nie wystarczy, gdy mamy do czynienia z liczbami. Podpisany 8-bitowy int (int8_t) może reprezentować tylko -128 -> +127. Unsigned (uint8_t) może reprezentować tylko 0 -> 255.

8-bitowe liczby całkowite są dość ograniczające. C / C ++ int musi reprezentować co najmniej -32.278 -> +32.767, więc odwzorowuje na int16_t - najmniejszy rozmiar, który to zrobi. Zapewnia to dobrą równowagę zasięgu i wydajności. Jest to szczególnie ważne, gdy początkujący się uczą - przepełnienie nie jest tak naprawdę czymś, co nieprogramiści rozumieją.

Wynika to jednak z wydajności, ponieważ większość operacji 16-bitowych zajmuje co najmniej dwa razy więcej niż operacja 8-bitowa i używa dwa razy więcej rejestrów. To może, ale nie musi, mieć dla ciebie znaczenia.

Wielu z nas przełącza się na typy natywne, takie jak int8_t i uint8_t, ponieważ daje to znacznie większą kontrolę.

Cybergibbons
źródło
3
Tylko uwaga: to nie zespół Arduino odwzorował int na int16_t, „int” jest słowem kluczowym zarezerwowanym dla C / C ++, a mapowanie typów jest częścią ABI ( gcc.gnu.org/wiki/avr-gcc ), że Programiści kompilatora avr-gcc postanowili pójść w ich ślady. Kolejną zauważalną różnicą jest typ „podwójny”, który zwykle ma szerokość 64-bitową, podczas gdy w avr-gcc jest 32-bitowy jak „float”
cmaglie
Dzięki. Nie jestem pewien, dlaczego to napisałem. Wiem, że int musi reprezentować 32.678 -> +32.767 (choć tak naprawdę myślę, że istniał zastrzeżony kompilator dla jednego z procesorów NEC, który tego nie przestrzegał). Myślę, że dzieje się tak, ponieważ nie lubię ukrywać szerokości w systemach osadzonych - użycie int16_t jest znacznie bardziej przejrzyste.
Cybergibbons
1
+1 za użycie czystych rodzimych typów! W Arduino Due intjest 32-bitowy! arduino.cc/en/Reference/int
Ron
3

Ważnym faktem na temat języków C i C ++ jest to, że ich odpowiednie standardy nie definiują rozmiaru (w bajtach) typów liczb całkowitych i zmiennoprzecinkowych.

Po prostu definiują minimalne zakresy i relacje między nimi, np

range(short) <= range(int) < range(long)

Wielkość np. A intzazwyczaj zależy od:

  • platforma docelowa (procesor)
  • sam kompilator
jfpoilpret
źródło
mówisz, że sizeof(short) == sizeof(int) == sizeof(long)jest możliwe?
Ron
@ ron-e Teoretycznie tak, byłoby to możliwe. W praktyce jednak nigdy tego nie widziałem. W większości kompilatorów / platform można się tego spodziewać (choć nie jest to narzucone) sizeof(short) < sizeof(long).
jfpoilpret