Mam pytanie..
Czy to:
*(tab+i);
jest na prawdę szybszę (jeżeli tak to o ile)
od tego:
tab[i];
i czy jest odpowiednik tej notacji dla tablic wielowymiarowych??
W internecie ludzie mówią różnie..
Mam pytanie..
Czy to:
*(tab+i);
jest na prawdę szybszę (jeżeli tak to o ile)
od tego:
tab[i];
i czy jest odpowiednik tej notacji dla tablic wielowymiarowych??
W internecie ludzie mówią różnie..
sid90 napisał(a)
Mam pytanie..
Czy to:
*(tab+i);
jest na prawdę szybszę (jeżeli tak to o ile)
od tego:
tab[i];
Gcc stworzyl dluzszy troche kod dla *(tab+i) przy prostym tescie, ale to nie moze byc uznawane za wyznacznik tego, ktore jest szybsze dlatego tez nie wrzucam deadlistingu. Moim zdaniem oba odwolania powinny byc traktowane tak samo.
wiesz co to arytmetyka wskaźników?
int b[][2] = { {2, 12}, {22, 32} };
for( int i = 0; i < 2; ++i )
for( int j = 0; j < 2; ++j )
cout << *(*(b+i)+j) << " ";
Jest szybsze ale tylko z tego powodu, że kompilator musi to sobie przetłumaczyć i tak na "wersję wskaźnikową", więc tylko to jest opóźnieniem, a co za tym idzie nie jest to na tyle istotna różnica aby się nią przejmować. Jeśli ktoś szuka optymalizacji w takich miejscach to znak, że trzeba zmienić algorytm, a nie zapis tablic (oczywiście nie mówię o tobie):]
Pytałem sie z ciekawości, bo przypomniało mi się, że kiedyś mój wykładowca tak mówił:)
Mi się zdaje, że jeżeli jest różnica to tylko i wyłącznie w czasie kompilacji a nie wykonania programu.
int main(){
int t[100];
int i=0;
for(int aa=0; aa<1000; aa++)
for(int a=0; a<10000; a++)
for(i=0; i<100; i++)
//t[i]=i;
*(t+i)=i;
return 0;
}
Bez optymalizacji zapis *(t+i) jest chyba o niewielki procent szybszy (może margines błędu spowodowanego obciążeniem, ale nie sądzę).
Przy optymalizacji -O2 dzieje się coś dziwnego: sposób t[i] wykonuje się w "trybie natychmiastowym" (0.003s), a *(t+i) ok. 0.8 sek.
Widocznie optymalizator zauważył że ten kod to bzdura i go pominął. W wygenerowanym assemblerze rzeczywiście jest o połowę mniej kodu dla t[i].
Dodałem na koniec printf("%d", t[0]), żeby optymalizator nie pominął tej pętli. Czasy są porównywalne. Może to dlatego, że wygenerowane kody assemblera są identyczne znak w znak?
Czyli jeżeli kompilujesz z -O2 to nie ma znaczenia który sposób wybierasz.
Testowane na Linuksie z GCC 4.4.3
//EDIT: chyba wiem czemu w jednym przypadku optymalizator uznał tą tablice i pętle za głupotę, a w drugim nie. W t[i] kompilator od razu wie że pewnej zmiennej przyporządkujemy jakąś wartość. Ale jej nie pobieramy w żaden sposób. kompilator od razu zna docelowy adres
Przy *(t+i) kompilator musi najpierw obliczyć adres dla LVALUE. Pobiera wskaźnik t i dodaje do niego i. I w ten sposób kompilator stwierdza, że tablica (wskaźnik) t jest jednak potrzebny, bo jego wartość jest pobierana
Tak mi się przynajmniej wydaje.
@Razi91 zauważ, że za każdym odpaleniem wyniki będą inne!
ale qrcze, sam widzę, że zapis tradycyjny jest jakby szybszy od wksaźnikowego..
aaa i jakbyś wyświetlał tak: *(t+i)=i; tak zadeklarowaną tablice: tab[100]
to by sie raczej wysypało.
I w ogóle widzę, że takie mierzenie kompilatorem jest raczej do d**y.. Kod mający złożoność n^2 wykonuję się tyle samo co przypisanie w pętli.. Nie wiem o co tu kaman.
Moje zdanie jest takie, że szamanizm ze wskaźnikami jest trudniejszy do opanowania przez kompilator. Zwykłe odwołania tablica[indeks] powinny być prostsze do ogarnięcia i zoptymalizowania.