2014-10-07 8 views
7

Czytam książkę Kochana "Programowanie w C". W sekcji Wskaźnik i Tablice na s. 264 mówi:Dlaczego zapętlenie tablicy przy użyciu indeksowania tablic jest wolniejsze niż w przypadku dostępu do wskaźnika?

Ogólnie, proces indeksowania tablicy zajmuje więcej czasu na wykonanie niż robi proces uzyskiwania dostępu do zawartości wskaźnika. W rzeczywistości jest to jeden z głównych powodów, dla których wskaźniki są używane do uzyskania dostępu do elementów tablicy - wygenerowany kod jest ogólnie bardziej wydajny. Oczywiście, jeśli dostęp do tablicy nie jest generalnie sekwencyjny, wskaźniki nie wykonują niczego, jeśli chodzi o ten problem, ponieważ wyrażenie * (wskaźnik + j) zajmuje tyle samo czasu, co wykonywanie, podobnie jak tablica wyrażeń [j] .

Czy ktoś może wyjaśnić, co jest szybsze od czego? Konkretnie, jeśli prędkość macierzy [j] = prędkość * (wskaźnik + j) to, co jest proces indeksowania tablicy i co to jest proces dostępu do zawartości wskaźnika? Istnieją również pytania i odpowiedzi na SO, które wspominają, że tablica [j] jest konwertowana na * (array + j) podczas kompilacji, więc nie powinno być żadnej różnicy.

Podsumowanie: Podaj mi bardzo prosty przykład tego, co mówi Kochan. 2 fragmenty kodu i punkt na szybszym, nie muszą tłumaczyć, dlaczego jest to prawda.

+3

Od jakiego roku jest ta książka? – 2501

+1

Myślę, że to, co mówi Kochan, to że zwiększanie wskaźnika o wielkość elementu jest szybsze niż pomnożenie indeksu przez rozmiar elementu i dodanie go do adresu bazowego. Jest to jeden z tych przypadków, w których różnica jest na tyle mała, że ​​prawdopodobnie nie ma to znaczenia, a jeśli pracujesz na poziomie, na którym naprawdę ma to znaczenie, prawdopodobnie będziesz już świadomy różnicy. – Caleb

+0

http://stackoverflow.com/questions/4534617/lea-instruction – 2501

Odpowiedz

5

Spójrz na fragmencie

int arr[5] = {0}; 
int *p = arr; 
int c = 1; 

Teraz zobaczyć pętlę 1:

for(int i = 0; i < 5; i++) 
    arr[i] = c++ + 1; 

pętlę 2:

for(int i = 0; i < 5; i++) 
    *p++ = c++ + 1; 

Różnica pomiędzy tymi dwoma pętlami jest ich ciało. Pierwsza pętla zawiera arr[i] = c++ + 1. Jest to odpowiednik *(arr + i) = c++ + 1. Co to znaczy *(arr + i)?
Oznacza to, że:

  • Pobierz adres wskaźnika podstawowego.
  • Pobierz wartość i
  • Dodaj wartość i do adresu bazowego.
  • Usuń adres końcowy.

Podczas gdy w przypadku drugiej pętli jest korpus *p++ oznacza:

  • Pobiera wartość p
  • wyłuskiwania adres przed zwiększając ją.
  • Przyrost adresu przez 1.

Oczywiście drugi będzie działał szybciej. Ale dzisiaj nowoczesne kompilatory są wystarczająco inteligentne, aby zoptymalizować te kody i najprawdopodobniej uzyskasz taki sam wynik dla obu pętli.

+1

Chyba chodziło o 'int * p = arr;' –

+0

@MaciejSzpakowski; Ups! To była literówka. – haccks

+0

@ Dressvoter, czy chcesz wyjaśnić? – haccks

Powiązane problemy