Obecnie język C jest uważany za język niskiego poziomu , ale czy w latach 70. był uważany za język niski? Czy ten termin był nawet w użyciu?
Wiele popularnych języków wyższego poziomu istniało dopiero w połowie lat 80. i później, więc jestem ciekawy, czy i jak zmieniła się natura niskiego poziomu na przestrzeni lat.
programming-languages
c
history
joeyfb
źródło
źródło
Odpowiedzi:
Aby odpowiedzieć na historyczne aspekty pytania:
Filozofia projektowania została wyjaśniona w języku programowania C napisanym przez Briana Kernighana i projektanta C Dennisa Ritchie, „K&R”, o którym być może słyszałeś. Przedmowa do pierwszego wydania mówi
i wprowadzenie mówi
Lista jest wyświetlana przez chwilę, zanim tekst będzie kontynuowany:
(Mam tylko drugie wydanie z 1988 r., Ale poniższy komentarz wskazuje, że cytowany tekst jest taki sam w pierwszym wydaniu z 1978 r.)
Tak więc, wtedy używane były terminy „wysoki poziom” i „niski poziom”, ale C zaprojektowano tak, aby mieściło się gdzieś w widmie pomiędzy nimi. Możliwe było pisanie kodu w C, który był przenośny na różnych platformach sprzętowych, i to było główne kryterium, czy język był wówczas uważany za wysoki poziom. C brakowało jednak niektórych cech charakterystycznych dla języków wysokiego poziomu i była to decyzja projektowa na korzyść prostoty.
źródło
Zależy to od twojej definicji języka wysokiego i niskiego poziomu. Gdy opracowano C, wszystko, co było na wyższym poziomie niż asembler, było uważane za język wysokiego poziomu. To niski pasek do wyczyszczenia. Później terminologia ta została przesunięta do tego stopnia, że niektórzy uważają, że nawet Java jest językiem niskiego poziomu.
Nawet w wysokopoziomowym krajobrazie językowym lat 70. warto zauważyć, że poziom C jest dość niski. Język C to w zasadzie B plus prosty system typów, a B to niewiele więcej niż wygodna proceduralna / strukturalna warstwa składniowa do złożenia. Ponieważ system pisma jest dopasowywany retro w stosunku do nietypowego języka B, nadal można pominąć adnotacje typu w niektórych miejscach i
int
zostaną one przyjęte.C świadomie pomija drogie lub trudne do wdrożenia funkcje, które były już dobrze ugruntowane w tym czasie, takie jak
C ma kilka interesujących funkcji:
W czasie, gdy C został opracowany, inne innowacyjne języki, takie jak COBOL, Lisp, ALGOL (w różnych dialektach), PL / I, SNOBOL, Simula i Pascal zostały już opublikowane i / lub były szeroko stosowane w określonych obszarach problemowych. Ale większość tych istniejących języków była przeznaczona do programowania na komputerach mainframe lub były akademickimi projektami badawczymi. Np. Kiedy ALGOL-60 został po raz pierwszy zaprojektowany jako uniwersalny język programowania, niezbędna technologia i informatyka do jego wdrożenia jeszcze nie istniały. Niektóre z nich (niektóre dialekty ALGOL, PL / I, Pascal) były również przeznaczone do programowania na niskim poziomie, ale zwykle miały bardziej złożone kompilatory lub były zbyt bezpieczne (np. Brak nieograniczonych wskaźników). Pascal wyraźnie nie ma dobrego wsparcia dla tablic o zmiennej długości.
W porównaniu z tymi językami, C odrzuca „eleganckie” i drogie funkcje, aby być bardziej praktycznym w programowaniu na niskim poziomie. C nigdy nie był przede wszystkim projektem badawczym dotyczącym projektowania języka. Zamiast tego był pochodną rozwoju jądra Unixa na minikomputerze PDP-11, który był stosunkowo ograniczony pod względem zasobów. Ze względu na swoją niszę (minimalistyczny język niskiego poziomu do pisania Uniksa z kompilatorem jednoprzebiegowym, który jest łatwy do przeniesienia) C jest absolutnie doskonały - a ponad 45 lat później nadal jest lingua franca programowania systemów.
źródło
%r10
jako „statyczny wskaźnik łańcucha”, o którym dokładnie mówisz. W przypadku C jest to po prostu kolejny rejestr zadrapania z zapisem połączeń, ale myślę, że Pascal by go użył. (Funkcje zagnieżdżone w GNU C używają go do przekazywania wskaźnika do zakresu zewnętrznego, gdy taka funkcja nie jest wbudowana (np. Jeśli utworzysz wskaźnik funkcji, aby kompilator utworzył na stosie trampolinę kodu maszynowego): Dopuszczalność regularnych użycie r10 i r11 )a = b;
aby skopiować całą strukturę tak, jak to możliwe w ISO C89. Tak więc we wczesnym C typy zdefiniowane przez użytkownika były zdecydowanie drugiej kategorii i mogły być przekazywane tylko przez referencję jako argumenty funkcji. Niechęć C do tablic, a także Dlaczego C ++ obsługuje przypisanie tablic do struktur wewnątrz struktur, ale ogólnie nie?Na początku lat 70. C był oszałamiającym powiewem świeżego powietrza przy użyciu nowoczesnych konstrukcji tak skutecznie, że cały system UNIX można było przepisać z języka asemblera na C przy znikomej ilości miejsca lub wydajności. W tym czasie wielu współczesnych nazywało to językiem wysokiego poziomu.
Autorzy C, przede wszystkim Dennis Ritchie, byli bardziej ostrożni, aw artykule czasopisma Bell System Technical Journal powiedział: „C nie jest językiem wysokiego poziomu”. Z wykrzywionym uśmiechem i zamierzając być prowokujący, Dennis Ritchie powiedziałby, że to język niskiego poziomu. Głównym celem jego projektu dla C było utrzymanie języka blisko maszyny, a jednocześnie zapewnienie przenośności, czyli niezależności maszyny.
Aby uzyskać więcej informacji, zapoznaj się z oryginalnym artykułem BSTJ:
Dziękuję Dennis. Obyście spoczywali w pokoju.
źródło
Jak napisałem gdzie indziej na tej stronie, gdy ktoś określił wzorzec zarządzania pamięcią malloc / wolną pamięcią jako „programowanie niskiego poziomu”,
Dla kontekstu miało to miejsce na początku lat 90., długo po wydaniu C.
źródło
malloc()
, bezpośrednio dzwoniącbrk(2)
lubmmap(2)
zarządzając wynikową pamięcią. Jest to masywny PITA bez możliwych korzyści (o ile nie zdarzy ci się być wdrożenie coś malloc-like), ale można to zrobić.Wiele odpowiedzi odnosiło się już do wczesnych artykułów, w których stwierdzono, że „C nie jest językiem wysokiego poziomu”.
Nie mogę się jednak oprzeć stosowaniu: wiele, jeśli nie większość lub wszystkie HLL w tym czasie - Algol, Algol-60, PL / 1, Pascal - zapewniały sprawdzanie granic tablic i numeryczne wykrywanie przepełnienia.
Ostatnio sprawdziłem, czy przepełnienie bufora i liczb całkowitych było główną przyczyną wielu luk w zabezpieczeniach. ... Tak, wciąż sprawa ...
Sytuacja dynamicznego zarządzania pamięcią była bardziej skomplikowana, ale mimo to malloc / free w stylu C był wielkim krokiem wstecz pod względem bezpieczeństwa.
Więc jeśli twoja definicja HLL obejmuje „automatycznie zapobiega wielu błędom niskiego poziomu”, cóż, przepraszający stan cyberbezpieczeństwa byłby zupełnie inny, prawdopodobnie lepszy, gdyby C i UNIX nie miały miejsca.
źródło
popcnt
.Rozważ starsze i znacznie wyższe języki, które poprzedzały C (1972):
Fortran - 1957 (niewiele wyższy poziom niż C)
Lisp - 1958
Cobol - 1959
Fortran IV - 1961 (niewiele wyższy poziom niż C)
PL / 1 - 1964
APL - 1966
Plus język średniego poziomu, taki jak RPG (1959), głównie język programowania, który zastępuje systemy zapisu jednostek oparte na wtyczkach.
Z tej perspektywy C wydawał się językiem bardzo niskiego poziomu, tylko nieco powyżej makr asemblerów używanych wówczas na komputerach mainframe. W przypadku komputerów mainframe IBM makra asemblera były używane do dostępu do bazy danych, takie jak BDAM (podstawowa metoda dostępu do dysku), ponieważ interfejsy bazy danych nie zostały przeniesione do Cobola (w tym czasie), co skutkowało spuścizną połączenia zestawu i Programy Cobol są nadal używane na komputerach mainframe IBM.
źródło
Odpowiedź na twoje pytanie zależy od tego, o jaki język C pyta.
Język opisany w Dennis Ritchie's 1974 C Reference Manual był językiem niskiego poziomu, który oferował niektóre z wygody programowania w językach wyższego poziomu. Dialekty wywodzące się z tego języka również były niskopoziomowymi językami programowania.
Kiedy opublikowano normę C 1989/1990 C, nie opisywała ona języka niskiego poziomu, który stał się popularny przy programowaniu rzeczywistych maszyn, ale opisała język wyższego poziomu, który mógłby być - ale nie był wymagany - -implementowane na niższych poziomach.
Jak zauważają autorzy C Standard, jedną z rzeczy, które sprawiły, że język był użyteczny, było to, że wiele implementacji można było traktować jako asemblery wysokiego poziomu. Ponieważ C był również używany jako alternatywa dla innych języków wysokiego poziomu i ponieważ wiele aplikacji nie wymagało zdolności do robienia rzeczy, których języki wysokiego poziomu nie byłyby w stanie zrobić, autorzy Standardu zezwolili implementacjom na zachowanie się w dowolny sposób jeśli programy próbowały używać konstrukcji niskiego poziomu. W związku z tym język opisany w standardzie C nigdy nie był językiem programowania niskiego poziomu.
Aby zrozumieć to rozróżnienie, zastanów się, w jaki sposób Ritchie's Language i C89 mogłyby zobaczyć fragment kodu:
na platformie, gdzie „char” to 8 bitów, „int” to 16 bitów big-endian, „float” to 32 bity, a struktury nie mają specjalnych wymagań dotyczących dopełnienia lub wyrównania, więc rozmiar „struct foo” wynosi 8 bajtów.
W języku Ritchie zachowanie ostatniej instrukcji pobierałoby adres zapisany w „p”, dodawało do niego 3 * 8 + 2 [tj. 26] bajtów i pobierało 16-bitową wartość z bajtów pod tym adresem i następnym , dodaj jedną do tej wartości, a następnie zapisz tę 16-bitową wartość do tych samych dwóch bajtów. Zachowanie byłoby zdefiniowane jako działanie na 26. i 27. bajcie następującym po adresie pod adresem p, bez względu na rodzaj przechowywanego tam obiektu.
W języku zdefiniowanym w standardzie C, w przypadku, gdy * p identyfikuje element „struct foo []”, po którym następują co najmniej trzy bardziej kompletne elementy tego typu, ostatnia instrukcja doda jeden element do elementu y trzeci element po * p. Zachowanie nie byłoby zdefiniowane przez Standard w żadnych innych okolicznościach.
Język Ritchie był językiem programowania niskiego poziomu, ponieważ chociaż pozwalał programiście korzystać z abstrakcji, takich jak tablice i struktury, gdy było to wygodne, definiował zachowanie pod względem podstawowego układu obiektów w pamięci. Natomiast język opisany w C89 i późniejszych standardach definiuje rzeczy w kategoriach abstrakcji wyższego poziomu i definiuje tylko zachowanie kodu, które jest z tym zgodne. Wdrożenia wysokiej jakości odpowiednie dla programowania niskiego poziomu będą zachowywały się użytecznie w większej liczbie przypadków niż wymaga tego norma, ale nie ma „oficjalnego” dokumentu określającego, co wdrożenie musi zrobić, aby było odpowiednie do takich celów.
Język C wymyślony przez Dennisa Ritchiego jest zatem językiem niskiego poziomu i został uznany za taki. Język wymyślony przez Komitet ds. Norm C nigdy jednak nie był językiem niskiego poziomu przy braku gwarancji zapewniających wdrożenie, które wykraczają poza mandaty Standardu.
źródło