Dlaczego niektórzy programiści kategoryzują C, Python, C ++ inaczej? - w odniesieniu do poziomu


16

Biorę kurs wprowadzający na temat Pythona, a instruktor mówi, że Python jest językiem wysokiego poziomu, a C i C ++ to języki niskiego poziomu. To po prostu mylące. Myślałem, że C, C ++, Python, Java itp. To języki wysokiego poziomu.

Czytałem pytania przy przepełnieniu stosu na C, C ++ itp. I wszystkie wydają się odnosić do tych języków jako do wysokiego poziomu. Wydaje mi się, że niektórzy programiści używają tych terminów zamiennie.


1
Podobnie jak wiele innych, wysoki i niski poziom to uproszczenie - przydatne do zrozumienia, ale potencjalnie wprowadzające w błąd, jeśli zapomnisz, że jest to uproszczenie. Jaki poziom jest z pewnością względny, jak powiedzieli inni. Ale niekoniecznie jest to linia - istnieją różne kierunki, w których można streścić (np. Różne paradygmaty). To, że odchodzisz od abstrakcji maszyny, niekoniecznie oznacza, że ​​zmierzasz w kierunku odpowiedniej abstrakcji dla swojej aplikacji.
Steve314

Nawet punkt początkowy może się różnić. Na przykład IMO rachunek lambda jest bardzo niskim poziomem abstrakcji - dużo abstrakcyjnym w maszynie, ale jest to bardzo prosta abstrakcja, która służy jako punkt wyjścia dla języków funkcjonalnych do rozpoczęcia tworzenia abstrakcji na szczycie. W każdym razie rachunek lambda prawdopodobnie nie jest bliższy idealnej abstrakcji dla konkretnego zastosowania niż kod maszynowy.
Steve314

Odpowiedzi:


31

Poziom wysoki i niski to warunki względne, więc użycie zmieniło się z czasem. W latach 70. UNIX tworzył fale, ponieważ pokazał, że system operacyjny można pisać przede wszystkim w języku wysokiego poziomu: C. W tym czasie C uważano za wysoki poziom, w przeciwieństwie do asemblera.

Obecnie C jest uważany za język niskiego poziomu, ponieważ ani język, ani standardowe biblioteki nie zapewniają żadnej struktury danych chleba i masła, takich jak wektory, słowniki, iteratory i tak dalej. Możesz mieć wszystkie te struktury w programie C, ale w końcu sam je napiszesz. Python, Java itp. Są na wysokim poziomie w stosunku do C, ponieważ wiele standardowych struktur danych jest wbudowanych w język lub są częścią standardowych bibliotek. Od razu po wyjęciu z pudełka ułatwia programowanie na bardziej abstrakcyjnym poziomie.

Poziom C jest niski w drugim sensie: umożliwia bezpośrednią manipulację sprzętem komputerowym (przynajmniej tak bezpośrednim, jak pozwala na to system operacyjny). Najpopularniejsze implementacje języka Python, Java itp. Są co najmniej o krok dalej usuwane ze sprzętu, ponieważ działają na maszynie wirtualnej. Jeśli chcesz manipulować sprzętem w Pythonie, musisz napisać rozszerzenie do maszyny wirtualnej Python, zwykle w C lub C ++.

C ++ to dziwny przypadek. Zapewnia mnóstwo ładnych struktur danych w ramach standardowej biblioteki, ale umożliwia także manipulowanie sprzętem na niskim poziomie.


3
C ++ nie jest tak dziwnym przypadkiem, IMO - to po prostu język mieszany. Poziom abstrakcji zależy od używanych funkcji.
Steve314

1
@ Steve314: Tak i nie: normalnie abstrakcja zawiera ukrywanie informacji, tzn. Język lub biblioteka są jak czarna skrzynka, która zapewnia interfejs, i nikt nie chce wiedzieć, co jest w czarnej skrzynce. C ++ jest nieco dziwny, ponieważ oferuje konstrukcje wyższego poziomu, ale nie uniemożliwia programiście dostępu do ich reprezentacji i ich złamania. C ++ to jedyny znany mi język, który nie izoluje różnych warstw abstrakcji (ale być może istnieją inne języki, których nie znam).
Giorgio

1
@Giorgio - C ++ pozwala ukryć każdy szczegół implementacji - np. Uczynić go częścią prywatnych elementów wewnętrznych klasy, więc jedynym oficjalnym sposobem korzystania z niego jest publiczny interfejs tej klasy. Oczywiście możesz łamać zasady i mieszać pamięć tak, jak chcesz - ale w praktyce możesz to zrobić w dowolnym języku, który obsługuje tworzenie aplikacji w świecie rzeczywistym.
Steve314

@Giorgio - Weźmy na przykład Haskell. „Niebezpieczny” w tym przypadku zwykle oznacza brak odniesienia do przejrzystości (jak w unsafePerformIO). Istnieją IOReftypy, ale nie ma odpowiednika o którym reinterpret_castwiem i nie ma odpowiednika arytmetyki wskaźnika. Ale to nie znaczy, że jest bezpieczny przed ludźmi hakującymi z pamięcią. Aby być praktycznym językiem, Haskell musi łączyć się z rzeczywistymi systemami operacyjnymi i bibliotekami. Ma „interfejs funkcji zagranicznej”. Jeśli naprawdę chcę to obalić, wszystko, co muszę zrobić, to użyć FFI do napisania pierwotnych funkcji subversion.
Steve314

@Giorgio - Oczywiście może mi być trudno znaleźć wartości, które chcę zepsuć w pamięci, ale to samo może mieć zastosowanie w C ++, w zależności od tego, jak dobrze je ukryłem. Na przykład mogę użyć PIMPL . Jeśli następnie podam tylko kod obiektu i nagłówek dla biblioteki, która rozumie, na co to wskazuje, niedoszły wywrotowiec musi ponownie zaprojektować ten kod obiektu, aby dowiedzieć się, co obalić i jak.
Steve314

8

Pomyśl o tym w kategoriach ruchomej skali, od języków NISKIEGO poziomu aż po języki WYSOKIEGO poziomu. Gdy język przesuwa się w górę skali, od NISKIEJ do WYSOKIEJ, język zapewnia coraz większą abstrakcję od określonego interfejsu z komputerem.

Języki niskiego poziomu zostały napisane, aby jawnie kierować komputerem - pomyśl kod maszynowy i kod asemblera.

Języki WYSOKIEGO poziomu próbują wyodrębnić drobne szczegóły (szczególnie przydział pamięci i zwolnienie pamięci). Chodzi o to, aby zapewnić bardziej „naturalny” interfejs do programowania i, mam nadzieję, pozwolić programiście skoncentrować się na projektowaniu i produkcji.

Obecnie język C jest uznawany za język NISKI. Nadal ma kilka znaczących abstrakcji od kodu maszynowego i kodu asemblera, więc jest technicznie „wyższy” od nich. Nadal jednak zapewnia bezpośrednie adresowanie pamięci i nie zapewnia wyrzucania elementów bezużytecznych. Są to więc szczegóły, które programista musi zaprojektować.

Porównaj to z innymi językami, takimi jak Python, Ruby lub Haskell, a masz znacznie bardziej niejasny interfejs. Te języki mają duże biblioteki kodu, które usuwają większość poleceń komputera. Czy zastanawiałeś się kiedyś, co dzieje się ze zmienną w Pythonie, gdy opuszczasz lokalny zasięg funkcji lub ją usuwasz? Prawdopodobnie nie masz racji? A to dlatego, że w języku WYSOKIEGO poziomu nie musisz! Opiekują się alokacją / zwolnieniem pamięci.

Języki na wysokim poziomie mają tę zaletę, że funkcjonują. Pozwalają nam projektować i rozwijać się swobodnie (i bezpiecznie!).

Języki o niskim poziomie mają przewagę prędkości w większości przypadków. Interpretacja kodu WYSOKIEGO kosztuje. Poza tym fajnie jest pisać coś w „mowie komputerowej”.

Mam nadzieję że to pomoże


5

Wysoki poziom kontra niski poziom nie jest rzeczą czarno-białą, ale ciągłą skalą. Terminy są używane do opisania, jak blisko język programowania jest do sprzętu; im wyższy poziom, tym bardziej oddziela sprzęt.

Najniższym poziomem jest oczywiście binarny kod maszynowy - jest to dokładna reprezentacja, którą system operacyjny ładuje i podaje do procesora. Montaż to pierwszy poziom abstrakcji zbudowany na nim: zamiast kodu binarnego pisze się mnemoiki, czytelne dla człowieka kody symboliczne, które reprezentują instrukcje maszyny binarnej. Tego używali ludzie do programowania systemów przed UNIX.

C jest kolejnym krokiem w łańcuchu abstrakcji, łącząc wspólne wzorce w konstrukty kontroli przepływu i wyodrębniając instrukcje specyficzne dla maszyny w składni agnostycznej platformy, a te ostatnie abstrakcje były jednym z głównych czynników, które uczyniły UNIX zarówno rewolucyjnym, jak i bardzo udanym, ponieważ oznaczało to, że ten sam kod można skompilować dla dowolnej platformy bez większych zmian.

C ++ dodaje kolejną warstwę abstrakcji: dodaje klasy (abstrakcyjne tabele i kontekst przechodzące do składni OOP) neworazdelete (łączenie alokacji pamięci i inicjalizacji zmiennych w jedną konstrukcję), sprawdzanie typu kompilacji, szablony (czas kompilacji bezpieczny dla typu metaprogramowanie) oraz szereg udogodnień w czasie kompilacji, takich jak przestrzenie nazw, przeciążenie funkcji i operatora itp.

Python robi kolejny duży krok od sprzętu. C ++ nadal zapewnia programistom pełną kontrolę nad przydzielaniem pamięci i pozwala na bezpośrednią manipulację pamięcią RAM; Python dba o zarządzanie pamięcią. Ponadto zamiast kompilować kod do instrukcji natywnej maszyny, uruchamia go na maszynie wirtualnej; niesie to ze sobą ujemny wpływ na wydajność (co czasem może być ciężkie, ale zwykle nie jest to powód do zmartwień), ale pozwala także na porządne rzeczy, które byłyby trudne w C ++ i niezwykle trudne w C, takie jak manipulowanie funkcjami i klasami w trakcie uruchamiania czas, pobieranie nazw dowolnych obiektów w czasie wykonywania, tworzenie instancji klas według nazw w czasie wykonywania, łatanie małp itp. itp.

Kiedy więc ludzie dzielą języki na „wysoki” i „niski poziom”, narysują gdzieś dowolną linię i ta linia nie zawsze jest taka sama. W 1970 r. Linia znajdowała się między montażem a C (czynnikiem decydującym było wyodrębnienie instrukcji maszynowych specyficznych dla platformy); w 1987 roku mogło być gdzieś pomiędzy C i C ++; dziś może być pomiędzy C ++ a Javą (z decydującym czynnikiem jest automatyczne zarządzanie pamięcią).

Krótko mówiąc: wysoki poziom to przesuwana skala, a dla trzech języków, o których wspominasz, to C <C ++ <Python.


Powiedziałbym, że wysoki poziom kontra niski poziom nie jest jedną skalą, ale są dwiema osobnymi skalami. Niski poziom odnosi się do tego, jak dobrze język odnosi się do zachowania maszyny, podczas gdy niski poziom odnosi się do jego zdolności do zapewniania abstrakcji. C # jest bardziej językiem wyższym niż C99, ale jest również niższym poziomem niż język zdefiniowany w standardzie C, ponieważ zachowanie np. Używania wskaźnika „int” do przetwarzania „krótkich” wartości w tablicy dwa na czas jest zdefiniowany w C #, ale nie w C99.
supercat

3

Linia między językami „niskiego poziomu” i „wysokiego poziomu” zmienia się od czasu do czasu.
Na przykład:
W czasach systemu UNIX język C był językiem wysokiego poziomu.
Dzisiaj C nie ma struktur takich jak typy mapowania (słowniki), iteratory itp., Jakie mają dzisiejsze języki wysokiego poziomu, takie jak Python. Tak więc linia przesunęła się, a C spadł teraz do grupy niskiego poziomu.

Języki niskiego poziomu: Języki
te są „zbliżone” do tego, co maszyna może wykonać (najniższy poziom to: Kod zestawu!).
Pracując z tymi językami, programista musi myśleć o rzeczach najniższego poziomu, takich jak zarządzanie pamięcią. W tym sensie jesteś blisko sprzętu, z którym musisz bezpośrednio z nim pracować.

Języki wysokiego poziomu:
te języki odciągają Cię od sprzętu, ponieważ same zarządzają takimi rzeczami, jak pamięć. Podczas pracy z tymi językami, pamięć jest czynnikiem (oczywiście), ale nie pracujesz bezpośrednio ze sprzętem. Zamiast tego radzi sobie z tym język, odsuwając cię (być może wyżej) od niższego interfejsu sprzętowego.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.