Forumwieso wird meistens C verwendet
Raphael Weissler – Dienstag, 01. Februar 2005 16:00 Uhr

Hallo allerseits,

Mich würde es mal interessieren wieso unter Linux zum Großteil mit C entwickelt wird?!

Wenn man nach Beispielen oder irgendwelchen Programmierproblemen im Internet sucht werden dies meist in C dargestellt/beschrieben.

Ich persönlich hab nichst gegen C, ich hab mich mittlerweile daran gewöhnt.

C++ (dachte ich immer) ist doch viel mäachtiger oder etwa nicht?
Speziell wenn es um Netzwerk geht finde ich nur C erklärungen.

Ich hoffe ihr könnt mir stichhaltige Meinungen präsentieren, damit wenn ich das nächste mal gefragt werde wieso C und nicht C++,
ich wenigstens ein oder zwei plausibele Erklärungen dfür habe.

Gruß Raffzen

4 Antworten
Marc Rintsch – Dienstag, 01. Februar 2005 16:41 Uhr

C++ ist vielleicht mächtiger, aber auch ungleich komplizierter und damit fehleranfälliger. Objektorientierung mit manueller Speicherverwaltung kann ziemlich unangenehm werden, vor allem wenn dann noch Exceptions dazu kommen.

Das war dann der Punkt, wo ich aufgehört habe mich mit C++ zu beschäftigen. Wenn man einmal den Luxus einer höheren Programmiersprache genossen hat, dann möchte man eigentlich nicht in C++ programmieren. Wenn es aber auf Geschwindigkeit ankommt, dann ist C wieder eine gute Wahl als zusätzliche Sprache. Einfach, und sehr hardwarenah.

Malte Buck – Dienstag, 01. Februar 2005 17:43 Uhr

C++ ist genauso fehleranfällig wie C. Aber der objektorientierte Ansatz ist eigentlich eher für designstarke Sprachen. In C++ schleppt man zu viel Zeug mit.

BTW ist C++ selber eine höhere Sprache (3 Stufe). Viel drunter ist zwar nicht, aber alles ab C gilt als höhere Sprache.

mfg
Malte

Marc Rintsch – Dienstag, 01. Februar 2005 23:40 Uhr

Stufe 3? Auf welcher Skala? Was eine “höhere Sprache” ist und was nicht, ist keine feste Definition. C und Pascal galten auch einmal als höhere Sprachen. Mittlerweile fällt für mich keine Sprache mehr darunter, bei der man sich zum Beispiel selbst um so etwas lästiges und fehleranfälliges wie Speicherverwaltung kümmern muss.

Der objektorientierte Ansatz ist für so gut wie jede Sprache geeignet um sauberere Programme zu schreiben.

Murphy – Mittwoch, 02. Februar 2005 00:05 Uhr

Was eine “höhere Sprache” ist und was nicht, ist keine feste Definition. Im Gegenteil, dafür gibt es in der Informatik sehr wohl eine allgemein anerkannte Einteilung [1]. Auslegungssache sind lediglich solche Details ob z. B. reines C++ noch eine 4GL, mit fortgeschrittenen Toolkits und IDEs aber schon eine 5GL ist, wo Java mit all seinen Helferchen drumherum einzuordnen ist und ob für solche “der Zeit voraus”-Sprachen wie Smalltalk evtl. eine neue Stufe aufzumachen ist.
Es gibt auch immer wieder Anwendungsfälle wo manuelle Eingriffe in die Systemverwaltung bis auf Speicher- und Prozessorebene herunter zugunsten der Performance und Kontrolle in Kauf genommen werden – C ist deshalb für viele hardwarenahe Sachen immer noch aktuell, und auch wegen des geringen Verwaltungsoverheads im schlanken Kompilat (keine Klassen-/Objektverwaltung etc.).
Der objektorientierte Ansatz ist für so gut wie jede Sprache geeignet um sauberere Programme zu schreiben. Es ist möglicherweise mit vielen Sprachen machbar, mit viel Selbstdisziplin sauber OO zu programmieren (siehe C/GTK); wenn die Sprache das Konzept jedoch von Anfang an mit entsprechenden zweckgerichteten Konstrukten unterstützt geht’s sicherlich viel einfacher.

[1] http://de.wikipedia.org/wiki/Programmiersprache#Anf.C3.A4nge

Malte Buck – Mittwoch, 02. Februar 2005 00:07 Uhr

Stufe 1 ist die direkte Programmierung des Prozessors, wie zB durch Mikroprogrammierung. Stufe 2 ist der Assembler, immer noch sehr nah dran, aber man muss sich keine Zahlencodes mehr merken:).
Für diese Stufen benötigt man ein sehr tiefes Verständnis der Maschine. Der Assembler ist allerdings aufgrund seiner Lesbarkeit über der Mikroprogrammierung. Stufe 3 sind die hardwarenahen Sprachen, wie eben C und C++. Man muss sich noch selber um den Speicher kümmern, kann inline Assembler verwenden etc pp.
Darüber sind dann die interpretierten Sprachen, bei denen die Logik mehr in den Vordergrund tritt, wie viele Scriptsprachen oder Java.
Darüber kommen dann Sprachen wie Prolog, die fast nur noch aus Logik bestehen.

Ich weiß leider nicht mehr in welchem Buch diese Definition stand. Das persönliche Verständnis, was eine höhere Sprache ist, ist allerdings von Mensch zu Mensch unterschiedlich.

Den Spruch “Gute Programmierer haben schon immer objektorientiert gearbeitet” kenn ich, und kann auch sagen, dass da was dran ist. Je nach Sprache kann dieser Ansatz (wie auch andere, zB Design By Contract) mehr oder weniger gut umgesetzt werden. GTK ist ein Beispiel dafür, wie man diesen Ansatz in einer funktionale und prozeduale Umgebung presst.

Dazu kommt allerdings, dass die Verwaltung von Objekten in einer nicht-objektorientierten Umgebung eine hohe Disziplin fordert, da man alle Methoden abbilden muss. C++ sorgt zB schon dafür, dass ein Objekt erzeugt werden muss und lokale Objekte vernichtet werden. Java ist da noch weiter (über die Performanz des GCs kann man sich wochenlang streiten, also lassen wir das), da eine Referenz auf null, aka eine nicht initialisierte Referenz, bei Gebrauch eine Exception wirft. C++ tut dies leider nicht, was eines der Hauptprobleme bei der Implementation ist. Über Designpattern kann man das allerdings oft abfangen.

Zum Thema saubere Programme:
Versuch in Basic mal einen objektorientierten Entwurf zu implementieren, am besten einen größeren. Da hat man viel Spass mit.
Aber mal im Ernst, die workarounds und Hilfsfunktionen sind nicht wirklich der Hit. Für einen selber mag es ja angehen, aber sobald jemand von aussen anhand des Quelltextes verstehen soll, was das Teil macht, ist mancher Entwurf mit mancher Sprache doch mühselig. (Jaja, C Code ist selbsterklärend …).

mfg
mbuck

Murphy – Mittwoch, 02. Februar 2005 00:08 Uhr

Bitte entschuldigt die spätnächtliche Konfusion; C++ muß natürlich zwischen 3GL und 4GL gesucht werden, nicht eine Stufe höher.

Malte Buck – Dienstag, 01. Februar 2005 17:40 Uhr

Warum C? C hat den Vorteil, dass man sehr hardwarenah programmieren kann. Hardwarenahes programmieren ist dann wichtig, wenn man bestimmte Fähigkeiten der Prozessoren zB durch inline Assembler nutzen will. Zugleich lässt es sich jedoch schön portieren.

Das mit C++ ist so eine Sache. Klar, ein bisschen object-orientated ist nie schlecht, aber für nicht objekt-orientierte Probleme auch sinnfrei. C++ ist ja C mit ein paar Zusätzen (gut, ein paar vielen). Wenn man diese objektorientierten Teile weglässt ist man wieder bei C (weshalb auch zB die Netzwerkbsps häufig nur für C sind, die kann man 1:1 in C++ übernehmen).

Alternative Sprachen, die entweder komplett objektorientiert sind, wie Smalltalk oder Object-C, eignen sich allerdings nicht für einen Betriebssystementwurf.

Soviel warum Linux selber in C.

Die Programme unter Linux sind je nach Art und Zweck in verschiedenen Sprachen geschrieben. Überall wo man Performanz braucht, nimmt man C. Muss es auch noch ein schönes Design sind, nimmt man C++ (nichts gegen Design in C, aber manche haben da echt grausiges Zeug). Das Ergebnis ist schnell allerdings in vielen Fällen eher zusammengehackt.

Will man einen guten Entwurf, nimmt man wirklich höhere Sprachen, wie Java (was auf einer virtuellen Maschine läuft), Smalltalk oder Eiffel. Diese Sprachen machen den Quelltext wartbar und haben einen eindeutigen Entwurf. Im Falle Java allerdings benötigt man einen Kommodo-Prozessor (das ist ein Java-Prozessor) oder eine VM.

Eine weitere Variante sind interpretierte Sprachen (im Prinzip wird ja alles interpretiert, aber “höhere” interpretierte Sprachen) wie zB Shell-Scripte, Perl oder Python. Diese Sprachen tragen allerdings das Manko, dass nicht alle Interpreter wirklich schnell sind.

Der Ansatz den auch MS im Augenblick verfolgt ist der JIT, der Just-In-Time Compiler. Es wird ein Bytecode erzeugt (ähnlich wie in Java), der dann bei der Ausführung in richtigen Maschinencode übersetzt.

Bei der Geschwindigkeit ungeschlagen ist natürlich Assembler, allerdings ist der fast nicht portierbar (schon mal versucht ein Programm von einem CISC auf einen RISC zu portieren?), und erfordert ein sehr tiefes Verständis des Prozessors (große Befehlssätze, Interrupts, Pipelining). Außerdem ist die Entwicklungszeit viel zu hoch.

Du kannst zumindest davon ausgehen, dass alle Compiler der GCC auch genutzt werden (ja, auch Fortran).

mfg
Malte

Marc Rintsch – Dienstag, 01. Februar 2005 23:50 Uhr

Alternative Sprachen, die entweder komplett objektorientiert sind, wie Smalltalk oder Object-C, eignen sich allerdings nicht für einen Betriebssystementwurf.

Meinst Du mit Object-C zufällig Objective-C? Wenn ja, dann verstehe ich den Einwand nicht, dass es sich nicht für einen Betriebssystementwurf eignet, da es sich hier im Gegensatz zu C++ wirklich nur um C um ein paar OO Konstrukte erweitert handelt. Man kann also performancekritische Teile komplett in C schreiben und OO da benutzen wo es Sinn macht.

Bei der Geschwindigkeit ungeschlagen ist natürlich Assembler,

Handgeschriebener? Ich glaube nicht, dass heutzutage noch jemand mit vertretbarem zeitlichen Aufwand besseren Assemblercode für zum Beispiel einen P4 schreiben kann, als der Intel C Compiler produziert. Da muss man einfach zu viel über die komplexe innere Struktur des Prozessors wissen. Einzelne, spezialisierte Routinen ja, aber nicht ganze Programme.

Malte Buck – Mittwoch, 02. Februar 2005 11:11 Uhr

Ja, ich meinte Objective-C.
Die Prozesse innerhalb eines Betriebssystems lassen sich oft sehr gut durch serielle und funktionale Vorgänge beschreiben. Dazu kommt ein gewisser Overhead den die Objektverwaltung mit sich zieht.
Wenn man sich allerdings den Kommodo-Prozessor anschaut, dann könnte ein OOOS (sehr gute Akü) wieder Sinn machen.

Und es gibt auch Prozessoren abseits von Intel und AMD. Für den P4 ein komplexeres Tool komplett in Assembler zu schreiben ist sehr zeitaufwändig und vermutlich wirklich nicht schneller als der IntelC. Allerdings trifft das auf Microcontroller und Prozessoren nicht unbedingt zu. Auch kleinere Aufgaben auf einem RISC (innerhalb eines C-Programmes zB) lassen sich oft manuell schneller lösen (auf Kosten der Portierbarkeit).

mfg
mbuck

Kevin Krammer – Mittwoch, 02. Februar 2005 14:05 Uhr

aber für nicht objekt-orientierte Probleme auch sinnfrei

Seh ich nicht so, C++ hat auch in diesem Fall eine Vorteile, zB typsichere Standardcontainer der STL, Strings variabler Länger mit überladenen Operatoren für Zuweisung und Konkatenation, Templates, usw.

C++ ist ja C mit ein paar Zusätzen (gut, ein paar vielen)

Nein, leider wird es oft so verwendet, also sind dann Programme statt C++ meistens nur “C mit Klassen”

weshalb auch zB die Netzwerkbsps häufig nur für C sind, die kann man 1:1 in C++ übernehmen

Die Beispiele in der Sprache der Basis API zu halten ist immer sinnvoll, weil sie auch in andere Sprachen übertragen werden können, solange dort eine Möglichkeit besteht, C APIs zu verwenden.
Allerdings wird es in vielen Fällen sinnvoll sein, den Code für C++ nochmal zu überarbeiten, zum Beispiel im Falle der Netzwerkkommunikation eine Socketklasse zu erstellen, die all das Low-Level Zeug schön kapselt

Ich denke der Eindruck, dass in Linux sehr viel in C geschrieben ist, entsteht oft durch die Verwechslung von C++ und C durch den Betrachter.
Daneben haben C++-Bibliotheken auch oft zusätzlich eine C API, um sie universeller verwendbar zu machen, ist ja auf anderen Plattformen genau so.

Ich denke im Gegensatz zu anderen Plattformen ist also nicht das meiste in C sondern in C plus C++ geschrieben und weniger in anderen Sprachen, etwa Pascal oder Basic.

Michael Wasilewski – Samstag, 05. Februar 2005 15:13 Uhr

>> komplexeres Tool komplett in Assembler zu schreiben ist sehr zeitaufwändig

[1] http://www.menuetos.org

GoaSkin – Freitag, 04. Februar 2005 00:54 Uhr

Nachdem ich angefangen habe, mich in die QTlib hineinzuarbeiten, mußte ich mir die Frage stellen, was ich eigentlich programmiere, C++ oder QT?

Würde ich GTK programmieren, müsste ich mir diese Frage auch stellen. Bei den komplexen Frameworks auf die heutzuzage in der Regel aufgebaut wird, wird der Löwenanteil über die eingebundenen Funktionen gelöst. Mein Eindruck ist, daß man von den grundlegenden Dingen der Programmiersprachen nicht allzuviel verstehen muß, um mit einem solchen Frameworks umzugehen, sondern sich mit den Befehlen und Lösungsansätzen der Frameworks selbst herumschlagen muß.

Nach einem Anfängerkurs kann man direkt mit der Einarbeitung in GTK, QT und was es sonst noch gibt anfangen. Die Befehle der eigentlichen Programmiersprache finden kaum noch Verwendung. Interessant zu wissen ist nur der Syntax, die Schleifen die es gibt und wie die Deklarationen erstellt werden. Bei der QT-Programmierung sind selbst die klassischen Variablentypen kaum zu gebrauchen. Die Bibliothek bringt ihre eigenen, die letzendlich auf die klassischen Variablentypen aufbauen, aber hauptsächlich gearbeitet wird.
Ob QT, GTK, die Microsoft Foundation Classes, Cocoa, Carbon oder GnuStep – wohl alles ähnliche Fälle. Selbst Delphi/ Kylix ist im Grunde genommen ein Framework für Object Pascal. Man programmiert allerdings mit den Funktionen des Frameworks. Die Programmierer sagen sich, wir programmieren Delphi.

Ansonsten haben sich C und C++ als Standardsprachen eingebürgert, nach dem sie die einstige Standardsprache Pascal immer mehr verdrängt haben. Vor der Pascal-Ära war Basic die wichtigste Programmiersprache.

Daß hauptsächlich mit C und C++ programmiert wird, liegt allerdings auch daran, daß man öfters einmal spezielle Hardwarefunktionen sowie Schnittstellen zu anderen Programmen programmieren muß. Der Weg, den die Hersteller von Soft- und Hardware (auch Opensource) in der Regel dazu anbieten sind eine Bibliothek mit einem entsprechenden Header-File, in dem man nachlesen kann, welche Funktionen man nutzen kann. Dieses liegt in den seltensten Fällen für Pascal, Basic oder sonst etwas vor. Die Funktionen, um die Bibliothek anzusteuern müsste man für andere Sprachen umschreiben/ übersetzen. Aber da ist es bequemer, die Sprache zu benutzen, für die man so mit den notwendigen Erweiterungen versorgt wird und nutzt C(++).

Marc Rintsch – Samstag, 05. Februar 2005 23:29 Uhr

Das Verbinden von C und C++ Bibliotheken mit anderen Sprachen kann man
zumindest teilweise automatisieren. SWIG – Simplified Wrapper and Interface
Generator[1] kann zum Beispiel Tcl, Python, Perl, Guile (Scheme), Java, Ruby
und noch ein paar andere Sprachen mit C/C++ verbinden.

[1] http://www.swig.org/

Christian Stamitz – Sonntag, 06. Februar 2005 14:17 Uhr

Prinzipiell ist ja Java oder C# auch eine Art C oder C++, aber abgesichert und an ein bestimmtes Toolkit gebunden.

Mit C++ kann man auch im herkömmlichen C-Stil schreiben und leider(?) tun es viele.

Pascal ist auch ähnlich C, nur lesbarer und sicherer. Diese Sicherheit geht verloren, wenn man objektorientiert programmiert und sich um Speicherverwaltung kümmern muss. Pascal ist textökonomisch ungünstiger.

Die Frage ist heute wie man den Programmierer syntaktisch davon abhalten kann Fehler zu machen. Ferner werden im betriebssystemnahen Bereich aber eben jene Funktionen gebraucht, die bei der Anwendungsprogrammierung zu Fehlern führen.

Coding Styles und die Toolkits sind heute wichtiger als die Sprache selbst.

Vom Syntax gesehen finde ich c# bzw. Java besser für die Anwendungsentwicklung geeignet, weil typische Fehlerquellen eliminiert werden. Tools wie Valgrind zeigen aber auch auf der anderen Front, dass es geht.

Was UNIX betrifft, so geht dieses Betriebssystem quasi in der Sprache C auf. C wurde populär durch UNIX.

Da der Schwerpunkt bei der Anwendungsprogrammierung heute auf den Toolkits liegt, kann man C++/Qt quasi als eigene Sprache auffassen.