2010-11-17 8 views
16

Często zdarza się, że wiesz, że twoja pętla nigdy nie będzie działać więcej niż x liczba razy, gdy x może być reprezentowany przez bajt lub krótki, w zasadzie typ danych jest mniejszy niż int.Dlaczego liczba całkowita jest zawsze używana jako zmienna sterująca w pętli for?

Dlaczego używamy int, który zajmuje 32 bity (z większością języków), gdy wystarczy coś takiego jak bajt, który ma tylko 8 bitów.

Wiem, że mamy 32- i 64-bitowe procesy, dzięki czemu możemy łatwo pobrać wartość podczas pojedynczej podróży, ale nadal zużywa ona więcej pamięci. Albo czego tu brakuje?

AKTUALIZACJA: Tylko w celu wyjaśnienia. Wiem, że szybkość nie ma żadnej różnicy. Pytam o wpływ na zużycie pamięci.

+0

Naprawdę? Większość kodu widziałem używa pewnej formy typu unsigned. –

+1

@Billy ONeal: w niektórych osadzonych mikropoleceniach typ bez znaku może oferować lepszą wydajność niż podpisany, kosztem większej ostrożności przy logice zakończenia pętli. Z drugiej strony, jeśli procesor taki jak ARM przechowuje coś podobnego do uint16 w rejestrze 32-bitowym, musi dodać dodatkowy kod, aby "przyciąć" wartość do 16 bitów. Żaden taki kod nie byłby potrzebny z int16 (ponieważ wszystko może się zdarzyć, gdy int16 ma przypisaną wartość poza zakresem -32768..32767, kompilator mógłby po prostu pozwolić swojej wartości zrobić wszystko, co jest wygodne). – supercat

+2

Czy tworzysz wystarczającą liczbę liczników pętli, gdzie zmiana ich typów ma * widoczny * wpływ na zużycie pamięci? Jeśli tak, to zgłaszam, że masz większe problemy niż tylko używanie czegoś szerszego niż konieczny. –

Odpowiedz

27

W C, określenie „int” definiuje się jako najbardziej efektywny rodzaj całkowitej obecnej maszyny.

Zwykle pasuje do rejestrów procesora, w ten sposób jest najbardziej efektywny.

Korzystanie mniejszy typ wartości całkowitej może spowodować pewnego przesunięcia bitowego lub bit maskowania na poziomie procesora więc nie dostaniesz zysk ...

+11

W rzeczywistości jest definiowany jako "naturalny rozmiar słowa", który może być lub nie być najbardziej wydajnym typem. Dla najbardziej wydajnego typu użyj fastint_t C99. –

+1

Coś na temat demistyfikacji tych szczegółów dotyczących programowania jest naprawdę ekscytujące. – sova

+0

Bardziej pytałem o zużycie pamięci. – uriDium

6

W wielu przypadkach licznik pętli zużywa dokładnie jeden rejestr procesora. Zmiana typu na 8- lub 16-bitową liczbę całkowitą nie zmienia tego, ponieważ rejestry mają stały rozmiar (32 bity na 32-bitowej platformie itp.).

Czasami licznik pętli może być umieszczony w pamięci RAM, np. gdy wywołujesz funkcję z pętli. Wtedy, tak, możesz zmarnować kilka bajtów, ale generalnie nie na tyle, aby się martwić. Przechowywanie i ładowanie licznika pętli może być wolniejsze, gdy używa się czegoś innego niż int.

8

Uzyskiwanie dostępu do rozmiaru całkowitego, który ma taki sam rozmiar jak rozmiar natywnego słowa, będzie najbardziej wydajne. Korzystanie z bajtów prawie na pewno wymaga tyle miejsca, co natywny rozmiar słowa i wymaga zmiany i maskowania w celu uzyskania dostępu, więc nic nie zyskuje.

W praktyce, jeśli nie masz bardzo, bardzo dużej pętli lub surowych ograniczeń czasowych, nie ma to większego znaczenia.

Ale jak zawsze, należy to, co jest najbardziej czytelny, a pierwszy punkt odniesienia/profile ...

+0

Bardzo wątpię, aby kompilator optymalizujący nie po prostu przydzielił 'int' przestrzeni dla tego' char', jeśli w rzeczywistości 'int' był bardziej wydajny. OTOH, na większości architektur, o których wiem, nie ma różnicy w prędkości między 'int' i' char'. –

7

I prawie zawsze używać int chyba że jest to bardzo dobry powód nie, tylko dlatego, że wszyscy z niego korzystają. Ma to na celu uniknięcie konieczności spędzania czasu przez następnego programistę. Dlaczego nie użył tutaj int, czy jest jakiś szczególny powód, dla którego muszę wiedzieć o.

Im więcej kodu , tym łatwiej będzie go odczytać w przyszłości.

+1

Dobra uwaga. Większość osób zna i potrafi zrozumieć składnię i ++. –

4

Pod względem Java Language Specification jest ciekawy punkt, aby pamiętać o zastosowaniu long i double:

Dla celów programowania modelu pamięci język Java, wykorzystując pojedynczy napisać do nie- lotna długa lub podwójna wartość jest traktowana jako dwie oddzielne zapisy : po jednej na każdą 32-bitową połówkę .Może to spowodować sytuację, w której wątek widzi pierwsze 32 bity o wartości 64-bitowej z jednego zapisu, a drugie 32 bity z innego zapisu. Zapisuje i odczytuje zmienne długie i wartości podwójne są zawsze atomowe. Zapisywane i odczytywane odwołania są zawsze atomowe, niezależnie od tego, czy są zaimplementowane jako 32 lub 64-bitowe wartości . Implementatorów VM zaleca się , aby uniknąć podziału ich wartości 64-bitowych , o ile to możliwe. Programiści są zachęcani do deklarowania wspólnych wartości 64-bitowych jako lotnych lub synchronizowania swoich programów poprawnie, aby uniknąć możliwych komplikacji.

Oczywiście to sprawia, że ​​za pomocą long lub double w zmiennej pętli mniej efektywne niż int w modelu pamięci Java, ale implementacje mogą się różnić w wydajności.

0

Kusi mnie, aby dodać coś tutaj, nawet jeśli jest to bardzo stary wątek. Nie zgadzam się w pełni z "Jestem świadomy, że prędkość nie ma żadnej różnicy". Rzeczywiście, bardzo często w pętli for jest indeksowanie tablicy takich jak

for (i=0; i<len; i++) s = A[i] 

Wtedy, nawet jeśli tablica jest wielkości mniej niż 128, widać znaczne różnice prędkości czy i jest int lub byte. Rzeczywiście, aby wykonać arytmetykę wskaźnikową w A[i], procesor musi przekonwertować twoją liczbę całkowitą na coś, co ma taki sam rozmiar jak wskaźnik. Jeśli liczba całkowita ma już ten sam rozmiar, to nie ma konwersji, która wywoła szybszy kod. Na maszynie 64-bitowej, wydaje mi się, 20% przyspieszenia na programach przy użyciu long int dla indeksów pętli na bardzo małej tablicy zamiast char (programy C/C++).

+0

To jest interesujące. Dzięki – uriDium

Powiązane problemy