Was ist der Unterschied zwischen Low-Level- und High-Level-Programmierung?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

"höhere" oder "niedrigere" Programmiersprache wird oft in Bezug auf Hardware-Ferne bzw. Hardware-Nähe verwendet.

Ich neige eher dazu, die "Höhe" einer Programmiersprache nach der konzeptionellen Abstraktion zu messen. Hardwarenähe ist nur eine hiervon, und auch diese hat mehrere Dimensionen.

Direkt an der Hardware ist man eigentlich nur mit Maschinensprache. Hier kann man ohne Verrenkungen direkt auf jede Speicherzelle und auf jede Ein-/Ausgabeadresse zugreifen. Bei Assembler -- wo eine 1:1-Übersetzung in und von Maschinensprache möglich ist -- kann man die Hardware-Adressen symbolisch benennen (und sollte das auch tun).

Eine extrem hardwareferne, aber m. E. nur "mittelhohe" Programmiersprache ist Java. Sie ist dafür gebaut, auf möglichst allen Plattformen eingesetzt zu werden, deshalb muss die JVM (Java Virtual Machine) zu 100 % von der aktuellen Hardware abstrahieren. Aber das Typsystem unterscheidet selbst noch innerhalb der Zahlenarten, es gibt 2 Typen von "Fließkommazahlen" (float, double) und 4 verschiedene Ganzzahltypen (byte, short, int, long), und um andere "Genauigkeiten" zur Verfügung zu haben, muss man eigens eingeführte Klassen (BigDecimal, BigInteger) verwenden.

Microsofts .NET-Sprachen sind vielleicht hardwarefern, aber waren anfangs ziemlich systemnah, da sie nur auf Windows-Betriebssystemen liefen (ohne Klimmzüge). Dafür soll die Umsetzung von "generics" besser gelöst sein (also Elemente, bei denen erst bei der Verwendung durch anderen Programmcode bekannt ist, welcher Typ nun verwendet wird).

Was z. B. C (und damit C++) und die .NET-Sprachen in eine andere Richtung "höher" macht, ist, dass man Funktionen/Methoden selbst in Variablen packen kann und als "Parameter"/"Argumente" an andere Funktionen/Methoden übergeben kann (was z. B. Java vom Konzept her nicht kann, man muss zu Umwegen und Tricks greifen).

Strikte (starke) Typisierung halte ich auch für ein Merkmal eher "höherer" Sprachen -- wenn man gleich bei der Definition oder Deklaration einer Methode/Funktion angeben kann, auf welche Typen sie wirken darf, spart man sich jede Menge Ärger. Insbesondere ist es sehr hilfreich zu sagen, "ich brauche hier zwei Variablen, die miteinander multipliziert werden können, egal, was diese Multiplikation im Einzelnen ist -- ob Zahlen, Vektoren, Matrizen, Zahl und Vektor, ...", oft per "Interfaces" gelöst. (Auch dies betrachte ich als "höher".)

Ob eine Typisierung statisch (unveränderlich) oder dynamisch ist, halte ich hauptsächlich für eine Konzeptfrage -- das würde ich nicht in die "Höhe" eingehen lassen. Hier geht es ja nicht um Performanz, die natürlich umso mehr optimiert werden kann, je mehr Informationen über eine Variable zur Kompilierzeit vorliegen.

Insgesamt ist die "Höhe" einer Programmiersprache also ein mehrdimensionales Konzept, was es nur in wenigen Fällen möglich macht, eine Programmiersprache sinnvoll "höher" als eine andere zu nennen.

-----

Wie sehr "hardwarenah" du mit C++ programmieren kannst, hängt auch von der Umgebung ab.

Wenn du C++.NET nimmst -- ein extremes Beispiel von Hardwareferne -- musst du "Unmanaged Code" verwenden, um auf hardwarenahe Elemente zugreifen zu können. .NET abstrahiert vom Konzept her völlig von der Hardware und weitgehend vom Betriebssystem.

Auf den meisten C++-Plattformen dürfte aber ein ziemlich direkter Zugriff auf die Hardware möglich sein (v. a. da C++ eine "Erweiterung" von C ist und C traditionell große Hardwarenähe ermöglicht).

-----

Aus Erfahrung spreche ich in Maschinensprache, Assembler, .NET-Sprachen (C#, VB.NET), Java und ein paar anderen Sprachen. C habe ich nie intensiv betrieben und meine Erfahrungen liegen schon Jahrzehnte zurück, C++ kenne ich hauptsächlich konzeptionell als C++.NET (mit seinen Marotten).

Woher ich das weiß:Berufserfahrung – Software-Entwickler
PWolff  11.07.2018, 16:23

Sehe gerade, dass es in der Frage selbst nicht um Programmiersprachen, sondern um Programmierung geht.

Auch in "Low-Level-Sprachen" ist oft "High-Level-Programmierung" möglich, wenn man entsprechende "Bibliotheken" hat und darauf verzichtet, "Low-Level-Elemente" zu verwenden. (Z. T. ist dies auch Betrachtungssache -- je nachdem, wie weit man "Boilerplate-Code" als "Low-Level-Zeugs" oder als "notwendiges Übel, das man aber vergisst, sobald es funktioniert" betrachtet.)

Für mich als Coder ist Boilerplate-Code aber etwas wirklich Lästiges, selbst wenn er von einem Tool automatisiert bereitgestellt wird -- ich will völlig von ihm abstrahieren und ihn auch nicht indirekt zu Gesicht bekommen. In diesem Sinne ist für mich eine Sprache umso "höher", je mehr sie mir das Programmieren (einschl. spätere Wartung/Erweiterung) erleichtert.

1
Kingworld 
Fragesteller
 11.07.2018, 17:46
@PWolff

Erst mal Danke für die ausführliche Antwort. Versucht man als Programmierer immer möglichst hardwarenah zu programmieren, damit das Programm schneller ist ?

0
PWolff  11.07.2018, 19:24
@Kingworld

Ganz bestimmt nicht immer. Wenn man nicht etwas wirklich Hardwarenahes programmiert - wie einen Treiber - oder riesige Datenmengen schnell "durchnudeln" muss - wie bei Datenbanken -, sind ganz andere Dinge wichtig. Besonders bei neuerer Hardware, die für die meisten Dinge ohnehin zigmal so schnell ist wie nötig.

Vor Allem, wen Business-Logik umgesetzt wird, sind Wartbarkeit und Erweiterbarkeit die wichtigsten Erfordernisse, deshalb programmiert man so, dass die Vorgehensweise des Algorithmus möglichst leicht verständlich ist (auch für andere) und dass leicht neue Funktionalität eingebaut werden kann. Dazu ist modulare Programmierung unverzichtbar. Die Objektorientierung war ein weiterer großer Schritt in diese Richtung - sie folgt (idealerweise ;-) ) dem Prinzip "Jeder ist für seinen eigenen Kram verantwortlich".

Das ist hier viel, viel wichtiger als ein paar Hundertstelsekunden.

Da der Mensch nur sehr langsam (nach Computermaßstäben) Informationen aufnehmen kann, spielt Geschwindigkeit auch bei Benutzeroberflächen eine untergeordnete Rolle. Es darf nur nicht so langsam weden, dass der Benutzer sich vera....t vorkommt.

Aber in den allermeisten Fällen gewinnt man Zeit nicht durch hardwarenähere Programmierung, sondern durch bessere Algorithmen. Dazu ist der Faktor, den man durch Hardwarenähe gewinnt, begrenzt, während er bei Algorithmengestaltung unbegrenzt ist.

1

Bei Lowlevel Programmiersprachen oder auch Hardwarenahe Programmiersprachen genannt kann man noch mehr oder weniger nach voll ziehen was der Prozessor aus der Anweisung macht.

Wenn ich in C schreibe if(i == 1) dann kann ich sagen, dass der Prozessor zunächst i und 1 auf gleichheit prüfen wird und dann mit einer konditionellen Sprunganweisung entscheiden wird ob der if Block ausgeführt wird oder nicht.

In höheren Programmiersprachen ist das nicht mehr so einfach zu sagen, so kann zB in C# der == Operator auch auf Objekte angewendet werden, wobei er hier meist die Instanzengleichheit beschreibt, in dem Fall wird der Prozessor je nachdem wie der JIT diese Anweisungen verarbeitet die beiden Instanzen auf gleichheit prüfen. Oder wenn der == Operator überschrieben wurde kann es auch sein, dass der Prozessor ganze Anweisungsblöcke ausführt und etliche Unterprogrammaufrufe ohne, dass ihm das der Programmierer direkt gesagt hat.

C++ ist eher bereits eine höhere Programmiersprache und nicht mehr ganz so Hardwarenahe wie C, obwohl C++ im Grunde nur eine Spracherweiterung von C ist.

Speziell der Begriff Hardwarenahe bedeutet, dass es dem Programmierer selbst überlassen werden sollte den Prozessor möglichst gut kontrollieren zu können. Eine Anweisung sollte also so wie sie der Programmierer auch schreibt vom Prozessor verarbeitet werden und nicht etwa komplett anders. So ist es zB in viele C Compilern auch möglich mittels Inline Assembler direkt auf die CPU Register zu zu greifen und zB direkt den Programmcounter zu speichern und zu verändern. Daraus folgt auch, dass Teile eine jeden Betriebssystems so geschrieben werden müssen, zB der Schedular, weil dieser direkten Zugriff auf die Register der CPU benötigt, welcher in höheren Sprachen kaum direkt möglich ist.