Czy młode umysły muszą nauczyć się koncepcji wskaźników?

89

Dlaczego mistrz C Dennis Ritchie wprowadził wskaźniki w C? I dlaczego inne języki programowania, takie jak VB.NET lub Java lub C #, je wyeliminowały? Znalazłem kilka punktów w Google i chcę też wysłuchać twoich komentarzy. Dlaczego eliminują koncepcje wskaźników we współczesnych językach?

Ludzie mówią, że C jest podstawowym językiem, a wskaźniki to koncepcja, która sprawia, że ​​C jest potężny i wyjątkowy, i sprawia, że ​​C nadal konkuruje z bardziej nowoczesnymi językami. Dlaczego więc wyeliminowali wskaźniki w bardziej nowoczesnych językach?

Czy uważasz, że znajomość wskaźników jest wciąż ważna dla nowych programistów? Ludzie używają obecnie VB.NET lub Java, który obsługuje bardziej zaawansowane funkcje niż C (i nie używa żadnych koncepcji wskaźników), a wiele osób, jak widzę teraz (moi przyjaciele), wybiera te języki ignorując C, ponieważ obsługują zaawansowane funkcje. Mówię im, żeby zaczęli od C. Mówią, że marnotrawstwem jest uczyć się koncepcji wskaźników, gdy robisz zaawansowane rzeczy w VB.NET lub Javie, które nie są możliwe w C.

Co myślisz?

Zaktualizowano :

Komentarze, które czytam w Google to:

  1. Wcześniejsze komputery były zbyt wolne i niezoptymalizowane.

  2. Korzystanie ze wskaźników umożliwia bezpośredni dostęp do adresu, co oszczędza czas zamiast tworzenia jego kopii w wywołaniach funkcji.

  3. Bezpieczeństwo jest znacznie gorsze przy użyciu wskaźników, dlatego Java i C # nie uwzględniły ich.

Te i jeszcze więcej tego, co znalazłem. Nadal potrzebuję cennych odpowiedzi. Byłoby to bardzo mile widziane.

niko
źródło
52
Java nie ma wskaźników? To nieprawda. Każde odwołanie do obiektu w Javie jest w zasadzie wskaźnikiem.
quant_dev,
20
Quant_dev oznacza, że ​​Java jest pełna wskaźników, które są używane w sposób przejrzysty, podczas gdy programiści nie mogą ich używać jawnie.
sakisk
9
Oto artykuł Joela Spolsky'ego, który jest istotny ... joelonsoftware.com/articles/fog0000000319.html
Joe Internet
11
„Dlaczego mistrz C Dennis Ritchie wprowadził wskaźniki c?” Wskaźniki nie zostały wprowadzone w punkcie c, pochodziły wprost z praktyki montażu, łącznie z nazwą.
dmckee,
14
@quaint_dev: Cóż, Java naprawdę nie ma wskaźników. Referencje nie mogą zrobić wszystkiego, co mogą zrobić wskaźniki, więc próba zrozumienia wskaźników w odniesieniu do referencji nie jest właściwą drogą (i błąd wielu programistów uczących się C lub C ++). Wskaźniki mogą wykonywać arytmetykę. Referencje nie mogą. (Ograniczenie, które naprawdę śmierdzi za każdym razem, gdy jestem zmuszony używać Javy)
Billy ONeal,

Odpowiedzi:

128

W tamtych czasach programiści pracowali znacznie bliżej metalu. C było zasadniczo wyższym poziomem zamiennika dla montażu, który jest prawie tak blisko sprzętu, jak to tylko możliwe, więc było rzeczą naturalną, że potrzebne były wskaźniki, aby skutecznie rozwiązywać problemy z kodowaniem. Wskaźniki są jednak ostrymi narzędziami, które mogą powodować duże uszkodzenia, jeśli są używane beztrosko. Również bezpośrednie użycie wskaźników otwiera możliwość wielu problemów związanych z bezpieczeństwem, które wtedy nie były problemem (w 1970 r. Internet składał się z kilkudziesięciu maszyn na kilku uniwersytetach i nawet nie był tak nazywany ...), ale odtąd zyskuje na znaczeniu. Tak więc obecnie języki wyższego poziomu są świadomie zaprojektowane w celu uniknięcia wskaźników surowej pamięci.

Powiedzenie, że „zaawansowane rzeczy zrobione w VB.Net lub Java nie są możliwe w C”, pokazuje co najmniej bardzo ograniczony punkt widzenia :-)

Po pierwsze, wszystkie te języki (nawet asembler) są kompletne, więc teoretycznie wszystko, co jest możliwe w jednym języku, jest możliwe we wszystkich. Wystarczy pomyśleć o tym, co się stanie, gdy fragment kodu VB.Net lub Java zostanie skompilowany i wykonany: w końcu jest tłumaczony na (lub odwzorowywany) kod maszynowy, ponieważ jest to jedyna rzecz, którą maszyna rozumie. W skompilowanych językach, takich jak C i C ++, można uzyskać pełną treść kodu maszynowego równoważną oryginalnemu kodowi źródłowemu wyższego poziomu, jako jeden lub więcej plików / bibliotek wykonywalnych. W językach opartych na maszynach wirtualnych uzyskanie bardziej reprezentatywnego kodu maszynowego twojego programu jest trudniejsze (i może nawet nie być możliwe), ale w końcu jest ono gdzieś w głębokich zakamarkach systemu wykonawczego i JIT.

Teraz oczywiście jest zupełnie inne pytanie, czy jakieś rozwiązanie jest wykonalne w określonym języku. Żaden rozsądny programista nie zacząłby pisać aplikacji internetowej w asemblerze :-) Warto jednak pamiętać, że większość lub wszystkie te języki wyższego poziomu są zbudowane na bazie ogromnej ilości kodu wykonawczego i kodu biblioteki klas, dużej części który jest implementowany w języku niższego poziomu, zwykle w C.

Aby przejść do pytania,

Czy uważasz, że wiedza na temat wskazówek dla młodych ludzi [...] jest ważna?

Pojęciem wskaźników jest pośrednictwo . Jest to bardzo ważna koncepcja i każdy dobry programista IMHO powinien ją zrozumieć na pewnym poziomie. Nawet jeśli ktoś pracuje wyłącznie z językami wyższego poziomu, pośrednictwo i referencje są nadal ważne. Niezrozumienie tego oznacza brak możliwości korzystania z całej klasy bardzo potężnych narzędzi, co poważnie ogranicza zdolność rozwiązywania problemów na dłuższą metę.

Tak więc moja odpowiedź brzmi tak, jeśli chcesz zostać naprawdę dobrym programistą, musisz także zrozumieć wskaźniki (jak również rekurencję - to kolejny typowy problem dla początkujących programistów). Być może nie musisz zaczynać od tego - nie sądzę, aby C był obecnie optymalny jako pierwszy język. Ale w pewnym momencie należy zapoznać się z pośrednią. Bez tego nigdy nie będziemy w stanie zrozumieć, w jaki sposób używane przez nas narzędzia, biblioteki i frameworki. A rzemieślnik, który nie rozumie, jak działają jego narzędzia, jest bardzo ograniczony. Szczerze mówiąc, można go zrozumieć także w językach programowania wyższego poziomu. Jednym dobrym testem lakmusowym jest prawidłowe wdrożenie podwójnie połączonej listy - jeśli możesz to zrobić w swoim ulubionym języku, możesz twierdzić, że wystarczająco dobrze rozumiesz pośrednictwo.

Ale gdyby nie cokolwiek innego, powinniśmy to zrobić, aby nauczyć się szacunku dla dawnych programistów, którym udało się budować niewiarygodne rzeczy za pomocą śmiesznie prostych narzędzi, jakie mieli (w porównaniu z tym, co mamy teraz). Wszyscy stoimy na barkach gigantów i dobrze jest nam to przyznać, niż udawać, że sami jesteśmy gigantami.

Péter Török
źródło
5
To dobra odpowiedź, ale tak naprawdę nie odpowiada na pytanie: „Czy młode umysły muszą nauczyć się koncepcji wskaźników?”
Falcon
11
+1 Dobra odpowiedź. Odrzuciłbym jednak argument dotyczący kompletności Turinga - dla praktycznego programowania jest to czerwony śledź, jak również zauważacie później. Jest to teoria obliczalności, tzn. Operacja ukończenia oznacza tylko, że w (dla wielu języków, nieskończonej) przestrzeni potencjalnych programów jest program, który implementuje ten sam algorytm, a nie to, czy jest to wykonalne, czy nawet możliwe z ludzkiego punktu widzenia. Samo wskazanie, że na końcu jest cały kod maszynowy, dowodzi tego również bez głupstwa: „Mogę robić wszystko w jednym języku, ponieważ wszystkie są takie same, harhar!” nasionko.
5
+1 za „A rzemieślnik, który nie rozumie, jak działają jego narzędzia, jest bardzo ograniczony.”
szybko_now
6
Ponadto niezrozumienie mechaniki wskaźników (i odniesień do rozszerzeń) w konsekwencji oznacza, że ​​nie rozumiesz koncepcji płytkiej / głębokiej kopii struktury danych, co może powodować poważne trudne do śledzenia błędy. Nawet w „nowoczesnych” językach wysokiego poziomu.
Mavrik,
1
C został zaprojektowany jako przenośny asembler dla Uniksa, tj. Blisko metalu.
39

Myślę, że musisz się różnić.

Java i inne języki wyższego poziomu nie usunęły wskaźników. To, co zrobili, to usunięcie zwykłej arytmetyki wskaźnikowej.

W rzeczywistości Java nadal pozwala na chronioną i ograniczoną arytmetykę wskaźników: dostęp do tablicy. W zwykłym starym C dostęp do tablicy jest niczym innym jak dereferencją. Jest to inna notacja, cukier syntaktyczny, jeśli chcesz, aby jasno przekazać, co robisz.
Nadal array[index]jest równoważne z *(array+index). Z tego powodu jest to również równoważne, index[array]chociaż przypuszczam, że niektóre kompilatory C mogą dać ci ostrzeżenie, jeśli to zrobisz.
W następstwie pointer[0]jest równoważne z *pointer. Po prostu dlatego, że „wskaźnik do tablicy” jest adresem pierwszego wpisu tablicy, a adresy kolejnych elementów są obliczane przez dodanie indeksu.

W Javie arytmetyka zwykłych wskaźników (odwoływanie się i dereferencje) już nie istnieje. Istnieją jednak wskaźniki. Nazywają je referencjami, ale to nie zmienia tego, czym jest. Dostęp do tablicy wciąż jest dokładnie taki sam: spójrz na adres, dodaj indeks i użyj tej lokalizacji pamięci. Jednak w Javie sprawdzi, czy ten indeks mieści się w granicach pierwotnie przydzielonej tablicy. Jeśli nie, zgłosi wyjątek.

Zaletą podejścia Java jest to, że nie masz kodu, który po prostu ślepo zapisuje dowolne bajty w dowolnych lokalizacjach pamięci. Poprawia to bezpieczeństwo, a także ochronę, ponieważ jeśli nie sprawdzisz przepełnienia bufora i tak, środowisko wykonawcze zrobi to za Ciebie.

Wadą tego jest to, że jest po prostu mniej wydajny. Możliwe jest programowanie bezpieczne dla pamięci w C. Nie można korzystać z szybkości i możliwości niebezpiecznego programowania w Javie.

W rzeczywistości nie ma nic trudnego w przypadku wskaźników lub arytmetyki wskaźników. Zwykle są one wyjaśnione w skomplikowany sposób, podczas gdy wszystkie wskaźniki są indeksami do jednej gigantycznej tablicy (twojej przestrzeni pamięci), wszystko, co odnosi się do wartości, daje indeks, gdzie ją znaleźć, wszystko, co robi dereferencja, to wyszukiwanie wartość przy danym indeksie. (Jest to tylko trochę uproszczone, ponieważ nie bierze pod uwagę, że wartości są różnej wielkości w pamięci, w zależności od ich rodzaju. Ale to jest poszlakowy szczegół, a nie część rzeczywistej koncepcji)

IMHO, wszyscy w naszej pracy powinni być w stanie to zrozumieć lub po prostu znajdują się w złym polu.

back2dos
źródło
13
+1 Java i C # nadal mają wskaźniki, i oczywiście NullPointerExceptions
jk.
5
Zauważ też, że odniesienia mogą z czasem wskazywać różne obszary, ponieważ śmieciarz przesuwa rzeczy. Wskaźniki są zwykle statyczne.
3
+1: to! I myślę, że istnieją dwie trudne rzeczy do zrozumienia w odniesieniu do wskaźników (ogólnie): pośrednia (która dzieje się w C, C #, Java, ...) i arytmetyka wskaźników (która nie dzieje się w Javie w ten sam sposób). Moim zdaniem oba są ważnymi pojęciami do nauki i oba są głównymi przeszkodami dla początkujących. Ale nie należy ich mylić: pośrednictwo może się zdarzyć bez arytmetyki wskaźnika.
Joachim Sauer,
2
Właściwie to back2dosmiał rację za pierwszym razem, ponieważ (array + index)już bierze pod uwagę rozmiar obiektów (w C).
Matthew Flaschen
4
@CyberSkull, odpowiedź dawała składniowy odpowiednik array[index]i to wszystko *(array+index). Jeśli chcesz pokazać, w jaki sposób kompilator działa wewnętrznie, możesz jawnie mówić o bajtach lub podawać zestawowi.
Matthew Flaschen
24

Pojęcie wskaźników jest ważne w ogólnej wiedzy dotyczącej programowania komputerowego. Zrozumienie tej koncepcji jest dobre dla przyszłych programistów lub programistów dowolnego języka, nawet jeśli język nie obsługuje go bezpośrednio.

Wskaźniki mają zastosowanie w strukturach danych (listy połączone) i projektach baz danych (klucz obcy).

Języki takie jak VB i C # mogą przekazywać dane przez „odniesienie” do metod, które można traktować jako rodzaj wskaźnika.

Zrozumienie, gdzie dane są alokowane w pamięci (stos vs. sterta) jest nadal ważne dla wydajności algorytmów.

Moim zdaniem ważna jest dobra znajomość podstaw.

Bez szans
źródło
Uważam, że ogólna koncepcja jest pomocna, ale nigdy nie znalazłem sytuacji, w której potrzebuję wskaźnika (oczywiście przy użyciu Java i PHP). Jedynymi przykładami, jakie moje kursy C ++ wymyśliły dla wskaźników, były ich użycie do tworzenia bardziej złożonych struktur danych, takich jak listy i słowniki, które istnieją w dowolnym języku programowania wysokiego poziomu na początku ..
Ben Brocka
2
W pewnym sensie masz rację, ale kiedy przekazujesz dane do metod, istnieje prawdopodobieństwo, że w niektórych przypadkach przekazujesz wskaźnik do zmiennej. Jednak koncepcja wskaźnika jest przydatna (moim zdaniem) niezależnie od jej implementacji w języku oprogramowania.
NoChance,
1
@SirTapTap: To dlatego, że jeśli nauczyłeś się C ++ w jakiś sposób, nauczą Cię C ++. Nie najlepszy sposób na użycie C ++. Arytmetyka wskaźnika jest zwykle nadpisywana, ponieważ jest to coś, co możesz mieć znajomość C ++ i nie wiedzieć. Ale nawet rzeczy takie jak iteracja po ogólnej kolekcji są wykonywane za pomocą wskaźników w real / idiomatic C ++. (Ponieważ jest to podstawa działania Standardowej Biblioteki Szablonów)
Billy ONeal,
@BillyONeal Wskaźniki były prawie w połowie kursu, naprawdę, nigdy nie znalazłem praktycznego zastosowania (inteligentnych) wskaźników jako programista, oczywiście, nigdy nie potrzebowałem takiej bezpośredniej kontroli nad pamięcią w czymkolwiek, co zrobiłem. Oczywiście zawsze istnieje możliwość, że kurs był źle nauczony, nie był to mój ulubiony.
Ben Brocka,
1
@SirTapTap: Praktyczne zastosowanie: każdy zbiór i algorytm w STL. std::sort, std::partition, std::find, Itd. Pracują ze wskaźnikami, a oni pracować z obiektami, które działają podobnie jak wskaźniki (iteratory). I pracują nad każdą ogólną kolekcją; połączone listy, dynamiczne tablice, deques, drzewa lub dowolny inny zbiór zdefiniowany przez użytkownika. Nie można tego rodzaju abstrakcji bez wskazówek.
Billy ONeal,
19

Tak, tak, tak, tak i tak !!!

Jeśli nie znasz podstaw, NIGDY nie będziesz w stanie rozwiązać naprawdę trudnych, dziwnych, trudnych i skomplikowanych problemów.

A jeśli naprawdę dobrze rozumiesz podstawy, jesteś DUŻO bardziej zbywalny na rynku pracy.


Raz pracowałem z facetem, który programował od 10 lat i nie miałem pojęcia, jak działają wskaźniki. Ja (znacznie więcej młodszy) spędziłem godziny na szkoleniu go na tablicy. To otworzyło mi oczy. Nie miał POMYSŁU na tak wiele podstawowych rzeczy.

Wiedz jak najwięcej.

szybko. Teraz
źródło
Ale co to są podstawy? Asembler, kod binarny?
SiberianGuy,
5
Podczas gdy twój ogólny punkt „wiedzieć tyle, ile możesz” jest rozsądny, kwestionowałbym pomysł, że „NIGDY nie będziesz w stanie rozwiązać naprawdę trudnych, dziwnych, trudnych i skomplikowanych problemów, które pojawią się na twojej drodze”, jeśli nie rozumiem wskaźników. To w jakiś sposób sugeruje, że wszystkie trudne problemy można rozwiązać za pomocą tych „magicznych” wskaźników, co nie jest prawdą. Pojęcia między wskaźnikami są przydatne do poznania, ale nie są bezpośrednio niezbędne dla wielu dziedzin programowania.
Dan Diplo,
4
@Idsa: nie, jeszcze bardziej podstawowe, wielu programistów obecnie nawet nie wie, jak tranzystory i bramki logiczne działają w „lepkich” układach scalonych, i na pewno powinny były wiedzieć, jak poruszają się elektrony i jaki jest wpływ niepewności kwantowej na miniaturyzację; Nie zacząłem nawet od szarlatanów, szminek i żubrów! i cząstki żubra czkawka!
Lie Ryan,
2
Podstawy .... rzeczy takie jak sposób przechowywania rzeczy. Różnica między bajtem, słowem, jak podpisany i niepodpisany działa. Jak działają wskaźniki? Co to za postać. Jak rzeczy są kodowane w ASCII (a obecnie Unicode). Jak można utworzyć listę połączoną w pamięci przy użyciu tylko prostych struktur. Jak NAPRAWDĘ działają struny. Z tych małych rzeczy wyrastają większe rzeczy.
szybko_now
5
Wiedz, jak możesz, to dobra zasada, ale myślę, że masz wózek przed koniem. Dobrzy programiści starają się nauczyć wszystkiego, co mogą, ponieważ są dobrymi programistami. Tęsknota za wiedzą jest cechą dobrego dewelopera. To nie jest przyczyna dobrego programisty. Wychodzenie i uczenie się jak najwięcej nie uczyni cię dobrym programistą. Dzięki temu będziesz chodzącą encyklopedią, niczym więcej. Jeśli jesteś dobrym programistą, TO MOŻESZ ZASTOSOWAĆ tę wiedzę, którą zdobyłeś, aby rozwiązać problemy. Ale jeśli nie byłeś już dobrym programistą, wiedza nie przyniesie wiele.
corsiKa
18

Tak, zrozumienie jest ważne.

Kilka miesięcy temu programowałem w języku C # i chciałem zrobić kopię listy. Oczywiście to, co zrobiłem, NewList = OldList;zaczęło się modyfikować NewList. Kiedy próbowałem wydrukować obie listy, obie były takie same, ponieważ NewListbył tylko wskaźnikiem do, OldLista nie kopią, więc właściwie OldListcały czas się zmieniałem . Nie zajęło mi to zbyt długo, ale niektórzy z moich kolegów z klasy nie byli tak szybcy i musieli wyjaśnić, dlaczego tak się dzieje.

Przykład:

List<int> a = new List<int>();
a.Add(2);
a.Add(9);
a.Add(8);
a.Add(1);
List<int> b = new List<int>();
b = a; //Does not make a copy, b is just a synonym!
b.Sort();
for (int i = 0; i < a.Count; i++)
{
    Console.WriteLine("a: " + a[i] + " b: " + b[i]);
}

I oczywiście wynik jest taki:

a: 1 b: 1
a: 2 b: 2
a: 8 b: 8
a: 9 b: 9

Umiejętność korzystania z nich nie jest tak ważna, ale ich zrozumienie jest kluczowe!

Bojan Kogoj
źródło
2
Najważniejsze jest, po co z nich korzystać i kiedy ich używać :)
niko
5
NewListbył tylko wskaźnikiem do OldList - NewLista OldListściślej mówiąc , oba były tylko wskaźnikami odnoszącymi się do tego samego Listobiektu.
Péter Török,
Ważne jest również, aby zrozumieć, że nowa lista, którą utworzyłeś, bnie ma już żadnych odwołań do niej, a teraz jest śmieciem.
TMN
14

Wskaż pojęcie! = Wskaż arytmetykę! = Wskaż składnię

Pierwsze ma zawsze znaczenie, jeśli potrzebujesz (i potrzebujesz) zrozumienia głębokiej / płytkiej kopii, przekaż referencję / przekaż wartość, itp. Pozostałe dwa mają znaczenie tylko wtedy, gdy Twój język du Jour pozwala ci z nich korzystać.

Alien Life Form
źródło
1
W dzisiejszych czasach musisz znać tylko podstawową koncepcję referencji, a nie składnię / matematykę wskaźnika. Nauczyłem się wskaźników (z arytmetyką i składnią) w C jeszcze w ciągu dnia. Języki, które teraz programuję, nie obsługują wskaźników w stylu C, które pozwalają ci robić niebezpieczne rzeczy. Można zrozumieć, dlaczego w pythonie a=[1,2]; b=a; a.append(3)oba ai oba bbędą odwoływać się do tego samego obiektu, [1,2,3]nie znając rzeczy takich jak w C, do ielementu th tablicy można się odwoływać przez oba arr[i]lub i[arr]jako oba *(arr+i). Wolę, gdy język nie pozwala na i[arr]użycie.
dr jimbob
Pozostałe dwa mają znaczenie tylko wtedy, gdy Twój język du Jour pozwala ci ich używać. ” - To zdanie nosi w sobie własnego autodestruktu. Jest mało prawdopodobne, aby język du Jour był tym samym językiem, który będzie używany jutro. A jutro możesz spotkać się z językiem obsługującym wskaźniki. Dolna linia? Lepiej, teraz zrozumiesz to raz i na zawsze. To nie jest takie trudne, ale warto.
JensG
14

Dlaczego mistrz C Dennis Ritchie wprowadził wskaźniki w C?

Ponieważ wskaźniki są bardzo silnym mechanizmem, z którego można korzystać na wiele sposobów.

I dlaczego inne języki programowania, takie jak VB.NET lub Java lub C #, je wyeliminowały?

Ponieważ wskaźniki są bardzo niebezpiecznym mechanizmem, który można wykorzystywać na wiele sposobów.

Myślę, że programiści powinni uczyć się o wskaźnikach, ale z edukacyjnego punktu widzenia nierozsądne jest wprowadzanie ich wcześniej. Powodem jest to, że są one używane do tak wielu różnych celów, więc jako początkujący trudno jest powiedzieć, dlaczego używasz wskaźnika w określonych okolicznościach.

Oto niepełna lista, do której służą wskaźniki:

  • alokacja dynamiczna ( new T)
  • struktury danych rekurencyjnych ( struct T { T* next; /* ... */ };)
  • iteratory nad tablicami ( for (T* p = &a[0]; p != &a[0] + n; ++p) { ... })
  • wspólny dostęp do obiektów ( T* new_pointer = existing_pointer;)
  • polimorfizm podtypu ( T* pointer_to_base = pointer_to_derived;)
  • starsze wywołanie przez odniesienie ( mutate(&object);)
  • typy opcjonalne ( if (p) { /* ... */ })

Zauważ, że użycie jednego mechanizmu dla wszystkich tych koncepcji pokazuje zarówno moc i elegancję doświadczonego programisty, jak i wielki potencjał dezorientacji dla kogoś nowego w programowaniu.

FredOverflow
źródło
Dlaczego mistrz C Dennis Ritchie wprowadził wskaźniki w C ? Ponieważ wskaźniki są bardzo potężnym mechanizmem, z którego można korzystać na wiele sposobów.” - Nie wiem na pewno, ale zgaduję, że ma to coś wspólnego z instrukcjami maszynowymi, które mają być zapakowane w język C, a poprzednicy programiści C.Asemblera są przyzwyczajeni do myślenia we wskazówkach, więc byłoby niespodzianka, jeśli nie użył tych dobrze znanych potężnych mechanizmów. Wszystko inne byłoby za daleko na lata 1978, a nawet lata 60.
JensG
12

Dlaczego? Możesz napisać ogromny system z projektantem formularzy i generatorem kodu. Czy to nie wystarczy? (ironia)

A teraz poważnie, wskaźniki nie są kluczową częścią programowania w wielu obszarach, ale pozwalają ludziom zrozumieć, jak działają elementy wewnętrzne. A jeśli nie będzie nikogo, kto rozumie, jak działają elementy wewnętrzne, wystąpi sytuacja, w której SQL2020, Windows 15 i Linux 20.04 zostaną zapisane na maszynie wirtualnej z odzyskiwaniem śmieci działającej na 30 warstwach abstrakcji, z kodem generowanym przez IDE, w JavaScript .

To zdecydowanie nie to, co chcę zobaczyć.

Więc tak, zdecydowanie muszą!

Koder
źródło
2
Dobry humor! +1 i całkowicie się zgadzam.
heltonbiker
7

Ani Java, ani C # nie wyeliminowały wskaźników, mają one odniesienia prawie takie same. To, co zostało wyeliminowane, to arytmetyka wskaźników, którą można pominąć w kursie wprowadzającym.
Żadna nietrywialna aplikacja nie byłaby możliwa bez koncepcji wskaźników lub referencji, dlatego warto ją uczyć (bez nich nie można wykonać dynamicznej alokacji pamięci).

Rozważ następujące kwestie w C ++ i Javie i myślę, że nie różni się to bardzo w C #:
aClass *x = new aClass();
aClass x = new aClass();
Tak naprawdę nie ma zbyt dużej różnicy między wskaźnikami a referencjami, prawda?
Należy unikać arytmetyki wskaźników, chyba że jest to konieczne, a także przy programowaniu za pomocą modeli wysokiego poziomu, więc nie ma w tym większego problemu.

Petruza
źródło
6

Profesjonalny programista powinien opanować wskaźniki.

Ludzie, którzy chcą poznać programowanie, powinni dowiedzieć się o jego istnieniu i implikacjach, ale niekoniecznie z nich korzystać.

Ludzie, którzy chcą rozwiązywać problemy osobiste za pomocą programowania (jak ja, którzy używają wielu skryptów Python), mogliby je w ogóle zignorować.

Cóż, to moja opinia ...; o)

heltonbiker
źródło
3

Wskaźniki zmiennych adresów są szczególnym przypadkiem bardziej uogólnionej koncepcji pośrednictwa. Pośrednictwo jest używane w większości (wszystkich?) Nowoczesnych języków w wielu konstrukcjach, takich jak delegaci i wywołania zwrotne. Zrozumienie pojęcia pośrednictwa pozwala dowiedzieć się, kiedy i jak najlepiej korzystać z tych narzędzi.

Dave Nay
źródło
3

Absufreakinglutly TAK ! Każdy, kto programuje, musi rozumieć wskazówki i pośrednie podejście.

Wskaźniki określają sposób uzyskiwania dużej ilości danych we wszystkich językach. Wskaźniki są cechą sprzętową wszystkich mikroprocesorów. Języki wysokiego poziomu, takie jak Java, VB i C #, zasadniczo uniemożliwiają bezpośredni dostęp do wskaźników od użytkowników języka z odnośnikami. Odnośniki odnoszą się do obiektów za pomocą schematu zarządzania pamięcią języka (może to być na przykład wskaźnik z metadanymi lub tylko liczba dla tabeli pamięci).

Zrozumienie, w jaki sposób działają wskaźniki, ma fundamentalne znaczenie dla zrozumienia, jak faktycznie działają komputery. Wskaźniki są również bardziej elastyczne i wydajniejsze niż odniesienia.

Na przykład powodem, dla którego tablice zaczynają się od zera, jest fakt, że tablice są w rzeczywistości skrótem dla arytmetyki wskaźników. Bez wiedzy o tym, jak działają wskaźniki, wielu początkujących programistów nie do końca otrzymuje tablice.

int a, foo[10];
foo[2] = a;

Wiersz 2 w arytmetyce wskaźnika byłby następujący:

*(foo + sizeof(int) * 2) = a;

Bez zrozumienia wskaźników nie można zrozumieć zarządzania pamięcią, stosu, sterty, a nawet tablic! Ponadto należy zrozumieć wskaźniki i dereferencje, aby zrozumieć, w jaki sposób przekazywane są funkcje i obiekty.

TL: DR : Zrozumienie wskaźników ma kluczowe znaczenie dla zrozumienia, że ​​komputery faktycznie działają .

CyberSkull
źródło
2

Myślę, że sprowadza się to do tego, że potrzeba radzenia sobie ze wskaźnikami zniknęła, ponieważ programiści mniej radzili sobie z bezpośrednim sprzętem, na którym pracowali. Na przykład, alokacja połączonej struktury danych listy w sposób, który idealnie pasuje do sekwencji 640-bajtowych modułów pamięci posiadanych przez specjalistyczny sprzęt.

Ręczne obchodzenie się ze wskaźnikami może być podatne na błędy (co prowadzi do wycieków pamięci i kodu, który można wykorzystać) i zajmuje dużo czasu. Tak więc Java i C # itp. Zarządzają teraz Twoją pamięcią i wskaźnikami za pośrednictwem ich maszyn wirtualnych. Jest to prawdopodobnie mniej wydajne niż używanie surowego C / C ++, chociaż maszyny wirtualne stale się poprawiają.

C (i C ++) są nadal powszechnie używanymi językami, szczególnie w komputerach o wysokiej wydajności, grach i przestrzeniach sprzętowych. Jestem osobiście wdzięczny, że dowiedziałem się o wskaźnikach, ponieważ przejście do referencji Javy (koncepcja podobna do wskaźników) było bardzo łatwe i nie zgubiłem się, gdy zobaczyłem swój pierwszy wyjątek NullPointerException (który powinien naprawdę nazywać się wyjątkiem NullReferenceException, ale dygresję) .

Radziłbym poznać pojęcie wskaźników, ponieważ wciąż stanowią one podstawę wielu struktur danych itp. Następnie wybierz język, w którym lubisz pracować, wiedząc, że jeśli pojawi się coś takiego jak NPE, wiesz, co się naprawdę dzieje .

Martijn Verburg
źródło
0

Oto obiektywna prawda:

Niektóre języki obsługują bezpośredni dostęp do pamięci (wskaźniki), niektóre nie. Istnieją dobre powody dla każdej sprawy.

  1. Jak ktoś tu powiedział, w czasach C automatyczne zarządzanie pamięcią nie było tak skomplikowane, jak dziś. W każdym razie ludzie byli do tego przyzwyczajeni. Dobrzy programiści wtedy znacznie lepiej rozumieli programy komputerowe niż nasze pokolenie (mam 21 lat). Używają kart dziurkaczy i dni oczekiwania na kompilację na komputerze mainframe. Prawdopodobnie wiedzieli, dlaczego każdy fragment ich kodu istnieje.

  2. Oczywistą zaletą języków takich jak C jest to, że pozwalają one na lepszą kontrolę nad programem. Kiedy tak naprawdę potrzebujesz ? Tylko podczas tworzenia aplikacji infrastrukturalnych, takich jak programy związane z systemem operacyjnym i środowiska wykonawcze. Jeśli chcesz po prostu opracować dobre, szybkie, niezawodne i niezawodne oprogramowanie, automatyczne zarządzanie pamięcią jest najczęściej lepszym wyborem.

  3. Faktem jest, że bezpośredni dostęp do pamięci był nadużywany głównie w trakcie tworzenia oprogramowania. Ludzie tworzyli programy, które wyciekły z pamięci, i faktycznie działały wolniej z powodu nadmiarowej alokacji pamięci (w C łatwo i często rozszerzano przestrzeń pamięci wirtualnej procesu dla każdej alokacji).

  4. Obecnie maszyny wirtualne / środowiska wykonawcze wykonują znacznie lepszą pracę niż 99% programistów przy przydzielaniu i zwalnianiu pamięci. Ponadto zapewniają dodatkową elastyczność przepływu, jaki chcesz mieć w swoim programie, ponieważ (głównie) nie zajmujesz się zwalnianiem przydzielonej pamięci we właściwym czasie i miejscu.

  5. Co do wiedzy. Myślę, że to godne podziwu, że programiści wiedzą, w jaki sposób wdrażane są środowiska, w których programują. Niekoniecznie do najmniejszych szczegółów, ale duży obraz.

Myślę, że znajomość działania wskaźników (przynajmniej) jest interesująca. To samo, co wiedza o tym, jak realizowany jest polimorfizm. Skąd proces bierze swoją pamięć i jak. Są to rzeczy, które zawsze interesowały mnie osobiście. Mogę szczerze powiedzieć, że uczyniono mnie lepszym programistą, ale nie mogę powiedzieć, że są koniecznością edukacyjną dla każdego, kto chce zostać dobrym programistą. W obu przypadkach większa wiedza często usprawnia pracę.

  1. Moim zdaniem, jeśli wszystko, co musisz zrobić, to stworzyć aplikację w Javie, C # lub coś w tym stylu, musisz skupić się na odpowiednich technikach projektowania i implementacji. Testowalny kod, czysty kod, elastyczny kod. W tej kolejności.

Ponieważ nawet jeśli nie znasz wszystkich drobnych szczegółów, ktoś, kto to zrobi, będzie mógł zmienić to, co stworzyłeś, w coś, co po prostu działa lepiej. I to często nie jest trudna praca, gdy masz odpowiedni, czysty i sprawdzalny projekt (i to zwykle większość pracy).

Gdybym był ankieterem, który chciałby zatrudnić kogoś do aplikacji na wysokim poziomie językowym, najbardziej interesowałyby mnie te rzeczy.

Wiedza na niskim poziomie to bonus. Jest dobry do debugowania i czasami tworzenia nieco lepszych rozwiązań. To sprawia, że ​​jesteś interesującą osobą, profesjonalnie. Daje ci szacunek w miejscu pracy.

Ale w dzisiejszym świecie nie jest to święte wymaganie.

Yam Marcovic
źródło
-1

Dla większości praktycznych celów w językach wysokiego poziomu OO wystarczające jest rozumienie odniesień, tak naprawdę nie trzeba rozumieć, w jaki sposób te języki implementują odniesienia pod względem wskaźników.

Istnieje o wiele bardziej funkcjonalne i nowoczesne podejście oparte na wielu paradygmatach, które ceniłbym o wiele wyżej niż możliwość wykonywania fantazyjnej arytmetyki wskaźników, by napisać, 1000-ty zoptymalizowaną funkcję kopiowania napisów, która prawdopodobnie działałaby gorzej niż String.copy twojej standardowej biblioteki w jakikolwiek sposób.

Radzę najpierw nauczyć się znacznie więcej różnych koncepcji na wyższym poziomie i rozgałęzić się, aby uczyć się języków różnych projektów, aby poszerzyć swoje horyzonty, zanim spróbujesz specjalizować się w sprawach sprzętowych.

Często widzę całkowicie nieudane próby mikrooptymalizacji serwletu WWW lub podobnego kodu w celu zwiększenia o 5%, gdy buforowanie (memoizacja), optymalizacja SQL lub po prostu tuning konfiguracji serwera WWW może przynieść 100% lub więcej przy niewielkim wysiłku. W większości przypadków majstrowanie przy wskaźnikach to przedwczesna optymalizacja .

Jürgen Strobel
źródło
-1

Zdecydowanie potrzebujemy dokładnej koncepcji wskaźnika, jeśli naprawdę chcesz być dobrym programistą. Powodem koncepcji Pointer był bezpośredni dostęp do wartości, która staje się bardziej wydajna i efektywna z ograniczeniami czasowymi ...

Ponadto, teraz kilka dni, biorąc pod uwagę aplikacje mobilne, które mają bardzo ograniczoną pamięć, musimy używać go bardzo ostrożnie, aby jego działanie było bardzo szybkie dzięki reakcji użytkownika ... Więc w tym celu potrzebujemy bezpośredniego odniesienia do wartości ...

Zastanów się nad urządzeniami Apple lub językiem Objective C, który działa wyłącznie z koncepcją wskaźnika. Wszystkie zmienne zadeklarowane w celu C mają wskaźnik. Musisz przejść przez wiki Celu C.

DShah
źródło
Dzisiejsze aplikacje mobilne mają więcej dostępnej pamięci niż niektóre centra danych C. Wiele aplikacji mobilnych jest napisanych w Javie lub bezpośrednio w html + javascript, wszystkie bez wskaźników (mają REFERENCJE). Tylko niewielka część bardzo wyspecjalizowanych programistów kiedykolwiek widzi warstwy systemu operacyjnego.
Jürgen Strobel