Die Seuche „C“
Zeit mich mal wieder unbeliebt zu machen, oder besser gesagt zu provozieren. Es geht um die für mich übelste Programmiersprache: „C“. Warum ist C so übel? Nun man könnte es auf den Punkt bringen, das hat dieser Aufsatz getan, der nicht von mir stammt, aber den ich übernommen habe. Fangen wir mal an mit einigen Mythen, die immer genannt werden, wenn es um die Vorteile von „C“ geht:
„C ist maschinennah und daher besonders gut geeignet für die Programmierung von hardwarenahen Programmen wie Betriebssystemen.“
Dieser Mythos mag in den siebziger Jahren gegolten haben, aber danach nicht mehr. Das hat nun auch weniger mit der Sprache zu tun, sondern mit dem Compiler, der den Code erzeugt. Für alle, die nicht so mit Assembler vertraut sind: die meisten Prozessoren haben Befehle die bei bestimmten Situationen geeignet sind und schneller ausgeführt werden als andere, sozusagen Spezialfälle. So verändern die Befehle INC und DEC einen Operanden um jeweils 1 und das Schieben eines Registers entspricht einer Division oder Multiplikation mit 2. Diese Operationen gehen schneller als eine Addition/Subtraktion oder Division/Multiplikation.
Derartige Operationen gibt es in C. Der Vorteil: Es ist so ein einfacher und effizienter Compiler erstellbar, da praktisch eine Arbeit des Compilers, nämlich den optimalen Code zu erstellen, auf den Programmierer ausgelagert wurde. Doch das ist keine Eigenschaft der Sprache, denn natürlich hindert niemand den Ersteller eines Compilers daran aus einer Instruktion wie a=a+1 den gleichen Code wie bei a++ zu generieren. Und das funktioniert nicht nur bei C so. Schon als in den achtziger Jahren Turbo Pascal herauskam schlug es viele etablierte C-Compiler, weil dieser Compiler so effizient war. Nur eben nicht mit der Sprache C, sondern Pascal.
Mit der Maschinennähe ist aber dann schon Schluss, denn wirklich maschinenah kann keine Hochsprache sein. Sie soll ja auf unterschiedlichen Prozessoren laufen. Erweiterungen, die es in C aber auch anderen Sprachen gibt, um Assemblercode einzufügen oder Betriebssystemroutinen aufzurufen sind nicht Bestandteil des Standards.
Mit der Geschwindigkeit von C ist es auch so, dass sie nicht an der Sprache fest machbar ist, sondern am Compiler. Microsoft reklamiert für sein .NET dass es unter Umständen schneller als C ist, weil diese Sprache erst zur Laufzeit übersetzt werden soll und dann die Befehle nutzt die der Prozessor unterstützt, während ein kompiliertes Programm sich immer an den kleinsten Standard halten muss. Wie ich schon erwähnte zeigte auch schon die Vergangenheit, dass andere Sprachen C leicht in Geschwindigkeit schlagen, wenn der Compiler entsprechend gut ist.
Diesen heute praktisch nicht mehr vorhandenen „Vorteilen“ stehen etliche Nachteile gegenüber.
Das erste ist, das C recht schlampig ausgelegt wurde, damit man wenig Aufwand mit dem Compiler hat. Es wurde auf fundamentale Sicherheitsüberprüfungen verzichtet, wichtige Funktionen wurden durch einfache, aber fehleranfällige Lösungen ersetzt und Verantwortung auf den Programmierer ausgelagert. Einige Beispiele:
Es ist in C, anders als in anderen Programmiersprachen bei if eine Zuweisung erlaubt also „if (c=5) “ anstatt „if (c==5)“. Das ist äußerst fehlerträchtig vor allem weil jeder von der Mathematik ja noch das „=“ als Vergleichsoperator kennt.
Die String-Bibliothek in C lagert praktisch die gesamte Verantwortung auf den Programmierer aus, denn es ist eigentlich keine Stringbibliothek: Es ist nur eine Konvention, dass ein String ein dynamisches Array ist der mit einer binären Null endet. Anders als wie bei vielen Gerüchten geglaubt wird, ist es auch nicht effizient. Denn bei allen Operationen die mit einem String nötig sind, muss man Zeichenweise das Array durchlaufen bis man die binäre Null findet. Ein System dass die Länge vor dem ersten Zeichen speichert wäre viel effizienter. Das erlaubt es Blockkopier/Verschiebebefehle von Prozessoren zu benutzen, die es schon bei 8-Bittern gibt.
Der Präprozessor ist im Prinzip eine programmgesteuerte Suchen/Ersetzfunktion. Ich bin beim Suchen/Ersetzen in meinem Quelltext sehr vorsichtig und nun soll ich das machen mit einem Text denn ich nicht mal, sondern nur der Compiler zu Gesicht bekommt? Vergiss es!
Das wohl problematischste und inzwischen auch allgemein bekannteste Sicherheitslücke von C: Der Buffer-Overflow. Er entsteht dadurch das Strings einer Routine nicht als Wertparameter, sondern als Zeiger übergeben werden. Die Routine muss dann in eine lokalen Variablen den String kopieren und wenn der Speicher hier kleiner als der String ist, dann überschreibt der String andere Variablen und die danach folgende Rücksprungadresse. Das wird ausgenutzt um verschiedene über das Internet erreichbare Dienste zu missbrauchen um Schadcode in Systeme einzuschleusen. So was ist nicht möglich bei Systemen die eine andere Stringverarbeitung haben wie z.B. Felder vor dem ersten Zeichen in denen die Länge steht und die es auch erlauben Strings anders zu übergeben.
Die Frage ist wie immer: was nützt es und was bringt es? Natürlich ist es von Vorteil, manchmal auf die niedrigste Ebene einer Maschine zu kommen. Doch dann halte ich es für besser eine definierte Schnittstelle zu Assembler einzubauen, weil dann der Benutzer weiß was er tut. So hat man eine Hochsprache kombiniert mit der Fehleranfälligkeit von Assembler. Der Nutzen für alle die nicht in Assembler programmieren wollen oder auf Betriebssystemebene gehen wollen ist aber nicht gegeben, sie müssen nur mit den Nachteilen leben. Mein früherer Informatikprofessor hat mal C als „Superassembler“ bezeichnet und das trifft es ganz gut. Nur ist leider C nicht so außer Mode gekommen wie Assembler….
Das verrückte ist, dass es einige Leute gibt, die so was lieben und die offensichtlich Einfluss haben, sonst hätte sich die Sprache nicht durchgesetzt. Das ist ein Kontrast zum täglichen Leben, wo wir in der Regel Sicherheit haben wollen und Leute die bewusst drauf verzichten, als Freaks ansehen. Also wenn jemand Fahrrad ohne Bremsen fährt oder ein Auto ohne Airbag, Gurte und Knautschzone herstellt, dann würde das wenig Verständnis bei den meisten anderen Leuten hervorrufen. 100 Stunden pro Wochen Programmierer mit Vorliebe für Pizza, Coke und Abneigung gegen Duschen und soziale Bindungen, also die die in Firmen rasch aufsteigen, scheinen aber genau das zu lieben und machen so Karriere und führen zum Einsatz von C den sie nun dank ihres Einflusses unternehmensweit durchsetzen können.
Okay, inzwischen hat man vieles entschärft. Compiler haben nun standardmäßig einige Optionen mit denen man die meisten Übel von C begegnen kann, aktiviert. Will man eigentlich standardkonforme Programme erstellen, muss man sie erst wieder deaktivieren. C hat sich auch weiter entwickelt, so diese unselige Definitionen der Funktionsköpfe im K&R Standard, die eigentlich keiner so richtig verstanden hat.
Das Problem ist natürlich das so ein System wie magisch alle Freaks anzieht und die dann darauf aufbauend noch schlimmere entwickeln, wie z.B. C++ (C erweitert um die Unverständlichkeit und Komplexheit), Perl (für alle die C Quelltexte zu verständlich und die Syntax zu leicht merkbar finden) oder Linux (ohne zwanzig Kommandozeilenoptionen für jedes Programm, die man sich nicht merken kann, nur halb so lustig) oder reguläre Ausdrücke (so einfach, dass es vom Entwickler ein ganzes Buch darüber gibt und natürlich ist die Standardeinstellung jedes RegEx Systems „gierig“, obwohl die Benutzer es meistens „nicht gierig“ haben wollen.
Ich denke anders: Entwicklungssysteme sollen mir das Leben einfach machen. Ich möchte schnell Programme entwickeln und nicht dauernd über Fehler stolpern, die man abfangen kann. Nennt mich Warmduscher oder Bequemlichkeitsfreak, aber ich bin zumindest kein Masochist. Wenn ich dran denke welche Probleme schon meine Studis mit einer Programmiersprache mit doppelten Airbags haben, ich wage nicht dran zu denken was passiert wenn die in C programmieren müssten…
Das größte Problem bei Einsteigern ist die Frage, wie man von einer Aufgabenstellung zu einem Algorithmus kommt. Das ist völlig unabhängig von der Programmiersprache, und alle Programmierhandbücher kümmern sich nicht darum. Im Grunde setzen sämtliche „Lehrbücher“ voraus, daß man schon programmieren kann. Sie lassen einen Einsteiger bei seinem Hauptproblem also völlig im Stich. Und wenn dann eine möglichst kryptische Programmiersprache dazukommt, mit jeder Menge Anfängerfallen und Stolperstricken, dann wird es noch schlimmer.
Die Grundlage von C stammt irgendwie noch aus der Anfangszeit der Computerei. Computer waren damals nichts was man verstehen mußte, sondern der Mittelpunkt der Welt. Und die Programmierer so etwas wie Schamanen, die Vermittler zur Computer-Geisterwelt. Und wie das bei Schamanen üblich ist, war dazu ein möglichst undurchsichtiger Hokuspokus nötig. So ein Aberglauben war C, und ist es bis heute. In der heutigen Zeit ist C genau so überflüssig wie Geister, Horoskope und Wünschelruten. Trotzdem gibt es immer wieder Leute, die noch darauf reinfallen.
Das stimmt so nicht. C entstand relativ spät, wenn man die Veröffentlichung von K&R Buches als Anhaltspunkt nimmt, wodurch die Sprache erst richtig bekannt wurde vier Jahre nach Pascal, 1976.
Als ich in den frühen achtzigern mit der Sprache erstmals konfrontiert wurde, galt sie noch als jung und hipp. Das kann auch nicht die kryptische Syntax erklären, denn wie schon gesagt mit Pascal gab es ja schon eine Vorlage die anders war und andere Vorlagen die relativ leicht verständlich war gab es auch.
Ich glaube viel eher das dies wirklich Absicht ist und bewusst so gemacht wurde.
Ich denke mal, dass sich C so durchgesetzt hat liegt darin, dass es seine Wurzeln in Unix hat und sich schon verbreitete, als der PC noch nicht erfunden war. Und wie so oft schleppt man das Erbe jahre- oder jahrzehntelang mit sich rum. Beispielsweise musste man als Windowsprogrammierer bis ins Jahr 2000 sich mit einer Beschränkung von Dateinamen plagen (8 3), die noch aus den 70ern stammt.
Vielleicht war dieses alberne Klischee von den pickligen Programmierfreaks, die Sonne und das andere Geschlecht nur in Pixelform kennen, mal einigermaßen zutreffend, aber das muss lange her sein. Ich habe mit Dutzenden von Programmierern gearbeitet oder sie zumindest ein wenig kennengelernt, und mir fallen nur zwei ein, auf die das halbwegs zutraf. Vor allem steigen diejenigen aber heutzutage nicht mehr auf, weil die alleinige Fähigkeit zu programmierern nur für die unterste Hierarchieebene reicht. Darüber braucht es zumindest Sozialkompetenz. In meinen letzten 3 Firmen ergab sich die Programmiersprache übrigens zwingend aus den Systemen und Anforderungen, in der ersten hat der Chef sie festgelegt (der vom Programmieren keinen Schimmer hatte).
C wurde aus BCPL entwickelt, was noch näher an Assembler ist als C.
Pascal war eine Reaktion von Niklaus With auf Algol68. Die Definition von Algol68 hat extrem lange gedauert, wohl um aus den Fehlern in Algol60 zu lernen.
Algol68 war dann sehr aufwendig zu implementieren, dafür aber leicht zu erlernen.
Die Sprache ist extrem orthogonal, es gibt wenig Ausnahmen.
Ich habe mit Elan und Algol68 programmieren gelernt, und war dann von Pascal sehr enttäuscht. Das Pascal unter VM/CMS war lausig, überhaupt keine String Verarbeitung vorhanden. Man hätte es zum wissenschaftlichen Rechnen nehmen können, aber dafür lernt man im Zweifelsfall dann doch noch Fortran.
VAX Pascal soll sher annehmbar gewesen sein, habe ich nie benutzen können.
Turbo Pascal war annehmbar, aber ausschließlich auf x86 PCs verfügbar.
Das Atari Pascal, was ich mir von meinem ersten selbst verdientem Geld gekauft habe, hätte ich beinahe an die Wand geklatscht, da die Einschränkungen auf damaligen Systemen (2 MByte RAM) nicht akzeptabel waren:
– Character Arrays haben 16 Bit pro Zeichen verbraten,
– Array Indicees waren auf 16 Bit Integer beschränkt.
Die erste wirklich schöne Sprache, die mir seit Algol68 untergekommen ist, war dann Modula3 (nicht von Wirth). Ganz grob Java mit Pascal Syntax und compilation in Objekt code.
Smalltalk habe ich ein gutes Jahr gelernt, aber die Syntax und Semantik ist so weit weg von Prozeduralen Sprachen und von Lisp, daß ich mich damit extrem schwer getan habe. Sollte man als erste Programmiersprache lernen, oder gar nicht.
Modula2 war dann auch nicht das gelbe vom Ei, und so blieb C als eine der wenigen Sprachen, die überall verfügbar waren.
Wie es bereits Andreas angesprochen hat ist glaube ich die Verfügbarkeit eine der großen Vorteile von C bzw. C . Wenn man nicht unbedingt Java verwenden will, etwa weil man eben aus bestimmten Gründen (und damit meine ich nicht die Performance, weil die ist glaube ich heutzutage bei Java auch kein so großes KO-Kriterium mehr) hardwarenäher Programmieren will oder weil die Oberflächenprogrammierung unter Java eine Strafe ist und man seinen Code trotzdem auf mehrern Platformen einsetzen will (Linux, Mac, Windows) kommt man eben an C/C nicht gut vorbei. Sicher gibt es andere Sprachen die besser sind (auch als Java) aber die sind dann eben entweder auch Scriptsprachen (muss nicht schlecht sein, aber es gibt dann natürlich Einschränkungen) oder nur für bestimmte Platformen verfügbar oder es sind Nischensprachen, die in bestimmten Dingen gut sind aber nicht als allgemeine Programmiersprache gedacht sind. C oder C sind eben so etwas wie der kleinste gemeinsame Nenner unter den Programmiersprachen. Und sicher sind C und C nicht unbedingt dafür geeignet portablen Code zu schreiben aber mit den entsprechenden Bibliotheken ist das eben relativ leicht.
Ursprünglich hängt das vermutlich mit Unix zusammen und damit das Programme unter Unix traditionell eben in C geschrieben wurden. In späteren Betriebssystemen wurde das eben zum Teil übernommen um die Portierung von Unixprogrammen auf diese Systeme zu erleichtern. Das ist glaube ich auch der Grund warum sich das so lange gehalten hat. Sicher gab es Betriebssystemansätze bei denen dann gleich auch eine neue Programmiersprache mit eingeführt wurde aber weil die Portierung sich dann als schwierig erwies haben sich diese Systeme nie so richtig durchgesetzt.
Moin Andreas Buschmann,
wo Du VM/CMS erwähnst, sollte PL/360 als wirklich hardwarenahe höhere Programmiersprache von Niklaus Wirth erwähnt werden. Da ich den Source des Compilers nicht per Google finden konnte, mal als http://pastebin.com/2jZpufS6
C hingegen ist von der Hardware abstrahiert, und quasi ein portabler Assemblerersatz. Da C Compiler für fast jede CPU verfügbar sind, ist es heute auch meist zwingend die Basis in der andere Programmiersprachen geschrieben wurden. Den Schritt, den Niklaus Wirth in oben zitierten Source macht, d.h. einen Compiler korrekt auf Papier zu schreiben, per Hand in Assembler zu übersetzen, um damit dann den Compiler zu compilieren macht heute kaum einer mehr, weil es ja C als quasi Assembler gibt.
Wenn man aber nicht gerade Compiler oder Betriebssysteme programmiert, ist C aller Wahrscheinlichkeit die falsche Wahl.
ciao,Michael
Gibt leider viele Fälle, in denen man nicht wirklich eine Wahl hat. iOS und OS X sind zum Beispiel solche Fälle, auch wenn es da nicht C, sondern Objective-C ist.
So pauschal kann man C nicht verurteilen, ich finde für den richtigen Zweck ist C durchaus angebracht. Für Embedded-Software auf kleinen Mikrocontrollern wie den AVR ist C immer noch wesentlich besser als in Assembler zu programmieren. Andere Sprachen scheiden aus weil entweder kein Compiler für den Prozessor zur Verfügung steht, oder der Code aufgebläht wird, was bei 16k Programmspeicher und 1k RAM sehr wichtig ist. Natürlich würde ich C hier nie für sicherheitskritische Sachen verwenden. Dort bietet sich eher Ada o.ä. an. Aber wenn ich „dirty performance hacks“ brauche und alles aus dem Mikrocontroller rausholen will kann ich nur Assembler oder C nehmen, und dann ist C das geringere Übel.
@Hiasl auch für Sicherheitskritische Sachen (SIL 3) wird teilweise C verwendet oder sogar vorgeschrieben. Wobei dann noch recht viel über statische Code Analyse tools herausgeholt wird.
Ich kenne keine Betriebssystem welches nicht in C geschrieben ist. Auch ein modernes Bios ist in C geschrieben. Es gibt also für gewisse dinge gar keine alternative. Es wird keiner gezwungen C zu verwenden. Ich selber würde keine Anwendung mehr in C schreiben, aber nicht weil ich die Sprache nicht mag sondern wie sie mir zu wenig funktionen als Sprachumfang bietet. Für Anwendungen ist .net sehr sinnvoll. Aber wenn ich wirklich mal die Kontrolle über das haben will was wirklich abläuft dann führt kein weg an C vorbei. Mit C kann man ebend alles machen, jede andere sprache hat irgendwelche Einschränkungen.
Die einfachheit der Sprache ist auch ihr vorteil. Es gibt keine Zwischenschicht die zusätzliche Fehler erzeugt oder sich im verhalten von Version zu Version ändert. Habe schon ausreichend Java Anwendungen gesehen die nach einem java update nicht mehr laufen.
Meinetwegen soll C als Sprache für Pofis zählen, sie läst wirklich zu viele Fehler für Anfänger zu, aber sie als seuche zu bezeichnen ist wirklich übertrieben.
> “if (c=5) ” anstatt “if (c==5)”.
ich habe beides schon verwendet und es macht auch beides sinn (wenn die 5 auch noch eine Variabel ist z.b. while( i = GetByte() ) { /*mach was mit i*/ } ). Wenn jemand = und == nicht auseinander halt kann dann kann er ja „if (5=c)“ schreiben, dann gibt es einen Fehler.
> Ein System dass die Länge vor dem ersten Zeichen speichert wäre viel
> effizienter. Das erlaubt es Blockkopier/Verschiebebefehle von
> Prozessoren zu benutzen, die es schon bei 8-Bittern gibt.
dann zeig mir doch mal den befehl auf einem AVR µC. Und was ist daran effizienter wenn ich ein byte mehr brauche? Und wie gross darf die länge werden 8bit, 16bit, 32bit, 64bit? Wenn es 16bit oder mehr ist dann ist es sogar sehr ineffizient auf einem 8bitter, wenn es dort nur 8bit ist dann ist es eine beschränken mit der ich auch nicht leben will. Und wozu brauche ich die länge überhaupt zum ausgeben oder kopieren? Ich arbeitet einfach bis eine kommt. Das es heute mit aktuellen PC nicht mehr um ein byte oder eine instuction geht ist ok, aber es gibt halt auch noch system mit mit 4Mhz und 2048byte ram laufen. Und da muss man sich schon ein paar gedanken mehr machen und das ist C schon luxus.
bekannte Betriebssysteme, die nicht in C geschrieben sind:
Z80: CPM
PDP11: RT11
VAX: VMS
IBM zSeries (360 ff.): Alle außer Linux und Unix
IBM pSeries (AS400 ff.)
das frühe MacOS
eigendlich alles auf Rechnern, eine Wort Architektur haben, und auf denen man nicht einfach auf einzelne Bytes zugreifen kann. (Macht C Compiler sehr häßlich.)
Ein weiteres Beispiel ist das in Assembler geschriebene russische PTS-DOS.
> Und wozu brauche ich die länge überhaupt zum ausgeben oder kopieren?
Um zu sehen, ob der String auch in den Zielbereich paßt. Bei jeder sinnvollen Sprache wird das automatisch überprüft. Bei C nicht. Wenn dann zu der schlampigen Sprache auch noch ein schlampiger Programmierer kommt, hat man die schönsten Sicherheitslücken. Mal ganz abgesehen davon, wenn man einen String vom Ende her bearbeiten will. Zum Beispiel beim Entfernen von Leerzeichen am Stringende. Da muß man in C erst den gesamten Strin vorwärts abklappern, bevor man mit der eigentlichen Bearbeitung anfangen kann. Was hier schon mal irgendwo gesagt wurde: Die beste Möglichkeit, ein Programm schneller zu machen, sind effizientere Algorithmen. Mit den C-Strings werden diese aber recht sorgfältig vermieden.
Und noch eins: Wo liegt der Vorteil von C bei der BIOS-Programmierung? Da muß man wirklich hardwarenah programmieren, nicht nur so tun. Und Portierbarkeit ist da garantiert kein Thema.
@Marcus: Einen Teil der Frage hat dir Andreas ja schon beantwortet. In sicherheitskritischen Systemen (Raumfahrt,Luftfahrt) gibt es auch kaum Betriebssysteme in C.
Du lieferst wieder genau das Standardargument der C-Fans, wenn man auf die elementaren Nachteile hinweist: Es wäre was für Profis und wenn man es nicht so könnte, dann könnte man ja die if Anweisung umschreiben. Das ist der grundsätzliche Denkfehler. Menschen machen fehler, auch Profis und eben nicht absichtlich, sondern zufällig. Das If Beispiel habe ich deswegen genannt weil ich miterlebt habe wie man zwei Stunden lang in dem Code nach dem Fehler suchte und das war kein Anfänger, sondern jemand der acht Jahre in C programmiert hatte.
Beim Auto sagst Du ja auch nicht: Wer Sicherheit will kann sich ja Airbags, Sicherheitsgurte und Knautschzonen montieren lassen. Man kann durchaus hardwarenah programmieren mit Sicherheit, dass zeigen Pascaldialekte mit Schnittstelle zur Hardware wie Turbo Pascal. Man muss diese mangelnde Fehlerabfrage nicht auf die ganze Sprache ausdehnen.
Zur Stringbibliothek: Delphi verwendet dynamische Strings (beliebige Länge) mit zwei verwaltungsfeldern (maximale Länge und aktuelle Länge) und allokiert den Speicher selbstständig und gibt ihn frei. Wenn Du einen kleinen Microcontroller als Referenz nimmst, dann kannst Du auch davon ausgehen, dass dort nicht viel Text ausgegeben wird. Dann stellt sich die Frage schon gar nicht. Ob man dann Strings mit einem Byte Verwaltungsfeld (maximal 255 Zeichen Länge) nimmt oder mit zwei ist dann wahrscheinlich auch nicht die Frage, wenn nur 2048 Bytes RAM vorhanden sind.
> Zum Beispiel beim Entfernen von Leerzeichen am Stringende. Da muß man in C
> erst den gesamten Strin vorwärts abklappern, bevor man mit der eigentlichen > Bearbeitung anfangen kann. Was hier schon mal irgendwo gesagt wurde: Die
> beste Möglichkeit, ein Programm schneller zu machen, sind effizientere
> Algorithmen. Mit den C-Strings werden diese aber recht sorgfältig vermieden.
man merkt sich einfach das letzte leerzeichen und geht bis zum ende durch, wenn man bei der 0 ist ersetzt man das letzte Leerzeichen durch eine 0 – fertig. Da zeigt nur wieder das man ebend mit dem verfahren mit beiden wegen zu sinnvoll zum ziel kommt. Die effizenz hängt jetzt davon ab ob ob mehr an anfang oder am ende abgeschnitten wird. Bei pascal müsste ich jetzt wieder an den anfang springen und die länge updaten.
> Und noch eins: Wo liegt der Vorteil von C bei der BIOS-Programmierung?
> Da muß man wirklich hardwarenah programmieren, nicht nur so tun. Und
> Portierbarkeit ist da garantiert kein Thema.
doch ist es, z.b die Wake On Lan sachen kann man überall weiterverwenden. auch das Booten über netzt will man nicht in ASM schreiben. Aus C kann man ja ohne Probleme auf speicher und Register zugreifen, diese werden dann einfach in ein header file ausgelagert und der eigentliche C code ist wiederverwendbar. Wer ASM und C programmiert der lernt schnell die vorzüge von C kennen. Das Bios wird meist nicht vom Boardhersteller programmiert. Es komt vom AMI oder Phoenix und dieser liefern das ganze als C code aus.
> bekannte Betriebssysteme, die nicht in C geschrieben sind:
ich hätte schreiben müssen, aktuelle Betriebssysteme. Klar wo es noch kein C gab konnte man es ja auch nicht verwenden.
Die Betriebssysteme in der Raumfahrt SIND aktuell. Dort gibt es auch nicht die üblichen Updates um Fehler auszubügeln, dort muss es schon am Anfang sicher sein.
In Pascal gibt es eine Trim und eine Setlength Funktion und wenn ich es händisch machen will, dann setze ich xyz[0]:=neuen_wert. Das ist ein Speicherzugriff, nicht mehr als bei C.
Mac OS 1-9 wurde (zumindest teilweise) in Pascal geschrieben. Zwar nicht aktuell, aber da war C schon sehr weit verbreitet. Und Teile von Windows und OS X sind in C plusplus bzw. Objective-C geschrieben.
Man sollte fairerweise vielleicht aber auch mal erwaehnen, dass C Bibliotheken einbinden kann 😉 und dass es wunderbare String-Bibliotheken gibt (die auch in fast jeder ernsthaften Anwendung verwendet werden), die alle Probleme, die die C-Stringbibliothek hat, beheben.
Auch andere Dinge, die man oft braucht, wie Hashes, „vernuenftige“ Arrays, Listen etc. gibt es als Bibliotheken.
Damit werden fast alle Nachteile von C behoben, und man behaelt die Vorteile groesstenteils.
In Pascal gibt es eine Trim und eine Setlength Funktion und wenn ich es händisch machen will, dann setze ich xyz[0]:=neuen_wert.
und wie gross ist nun xyz[0]? 16bit oder 32bit? Wenn xyz[0] 32bit ist dann müsste ja auch xyz[1] 32bit sein was eine Totale verschwendung ist. Keine Ahnung Ahnung wie das gehen soll. Bei Pascal war alles 8bit da war das kein Problem.
Das funktioniert so meines Wissens nur mit dem ShortString, der tatsächlich nur ein Byte für die Länge hat und deshalb auf 255 Zeichen beschränkt ist. Aber dann gibt es ja auch noch den längeren AnsiString, der bis zu 4GChars lang sein darf, sowie den WideString, der Unicode benutzt. Und zu guter Letzt noch PChar, was letzendlich ein C-artiger Pointer ist, mit allen Nachteilen von C.
Ich weiß allerdings nicht, was die neueste Version alles unterstützt und was dort der Standard ist.
Direkt funktioniert es nur bei Shortstrings. Aber auch in der Delphi RTL ist die Setlength Funktion nicht viel anders implementiert wie folgender Ausschnitt aus den Sourcen zeigt:
@@setLength:
MOV [EDX],AL
POP EBX
RET
Das grundsätzliche ist ja wie ich schon geschrieben habe, dass niemand einen Compilerhersteller daran hindern kann eine andere Sprache genauso effektiv oder vielleicht sogar effektiver (wie schon gesagt, in den achtzigern waren die C-Compiler langsamer als Turbo Pascal) zu implementieren. Die „erlaubten“ Tricks können dann sogar kontapoduktiv sein, weil sie eine Optimierung des Codes durch den Compiler verhindern.
Als ich 2003 in meiner Diplomarbeit bei Berechnungen C, C#, Java und Delphi verglichen habe, gab es keine signifikanten Unterschiede. Bei grafischen Oberflächen waren sie enorm (C schied damals aus, aber C# war deutlich langsamer und Java um den faktor 10 langsamer).
Soooo, nach ein paar Tagen jetzt auch mal mein Senf dazu…
Bei welchen 8-Bit Prozessoren gibt es Blockkopier/Verschiebebefehle ?
Präprozessor = Suchen und Ersetzen; Okay, das kann schon mal schwierig werden, vor allem, wenn umfangreiche Makros verarbeitet werden.
@Elendsoft: Das Problem mit der Aufgabenstellung und dem Algorithmus gibt es aber nicht nur in der Informatik. Das kann man auch in der Physik oder in der Mathematik haben, dass man lange rätselt, wie man von einem Problemzu einer Lösung kam bzw. kommt.
Was die Syntax von C angeht, die ja teilweise sehr wohl mit der von Pascal vergleichbar ist, so fand ich die grundsätzlich gewöhnungsbedürftig, was wohl daran lag, dass das Basic auf dem C-64 keinerlei strukturierung kennt, weshalb man einfach drauf los hacken kann, ohne vorher genauer nachdenken zu müssen. Für grössere Projekte ist das zwar die falsche herangehensweise, wie inzwischen allgemein bekannt ist, aber soweit war man bei den Heimcomputern in den 80ern ja nur Teilweise.
Für Strings gibt es mittlerweile auch eine Sichere Bibliothek, Secure-String-Library genannt. Ich weis aber nicht, ob die nur ein Microsoft-Produkt ist, weil ich sie bisher nur in Beispielen aus der MSDN gesehen habe, die sich mit dem WinAPI befassen. Aber das ist, wie schon geschrieben wurde, auch nur eine von mehreren.
Bezüglich der pro und contra Diskussion um C hier mal eine andere Meinung, die ich eben entdeckt habe, als ich auf den Seiten herum gestöbert habe. Die stammt von Prof. Jürgen Dankert von der Hochschule für Angewandte Wissenschaften Hamburg (HAW Hamburg), die früher mal als Fachhochschule Hamburg bekannt war.
.
.
Ach ja, und wo es doch auch um sichere Programme im Sinne grösst möglicher Fehlerfreiheit und geringer Angriffsmöglichkeiten durch provozierte Pufferüberläufe und ähnliches geht: Kennt sich hier jemand mit Ada aus? Die Sprache soll doch vieles gar nicht erst erlauben, was in C/C möglich ist, weshalb sie für kritische Systeme gern verwendet wird. Nicht nur vom US-Militär, das die Entwicklung mal angestossen und gefördert hat, sondern auch von der Luft- und Raumfahrtindustrie. – So hab ich zum Beispiel mal gelesen, dass die Steuersoftware der Ariane-Raketen in Ada geschrieben ist. – Deshalb die Frage: hat hier jemand Erfahrungen mit Ada? – Und wenn ja, was sind denn die signifikanten Unterschiede zu C bzw. C oder auch Pascal?
Der verlinkte Artikel ist sehr alt, das „neueste“ Update ist aus dem Jahr 2000.
Um vielleicht dazu meinen „Senf“ dazuzugeben: Ich wuerde heutzutage ohne mit der Wimper zu zucken jedem, der mir die Frage stellt „Was fuer eine Programmiersprache soll ich lernen?“, JavaScript empfehlen.
JavaScript ist sowohl prozedural als auch funktional als auch objektorientiert, alle drei Programmierparadigmen sind sehr sauber „eingebaut“, JavaScript ist inzwischen praktisch ueberall (DOM (Browser), Photoshop, Flash (ActionScript = JavaScript), WSH (Windows Scripting Host)), und man kann damit praktisch in jeder Umgebung jede beliebige Aufgabe loesen.
Nebenbei gibt es extrem schnelle JIT-Compiler fuer JavaScript, oft schneller als Java, und wenn man noch dazu auf extrem saubere Syntax steht, kann man zusaetzlich CoffeeScript erlernen, welches nach JavaScript transparent transkompiliert und sich praktisch wie englischer Text liest und ohne {}{{}{}{}{}{} auskommt.
Die Programmiersprache Ada ist Pascal in ganz groß.
Im Sprachumfang von Anfang an enthalten waren:
– modulare Programmierung inclusive opaker Datentypen
– Namensräume
– coroutinen
– parallele Konstrukte
– ausreichend große Datentypen
– default Parameter bei Prozeduren
– benamste Parameter bei Prozeduren
– Das compile und Link Environment ist Teil des Sprachstandards.
Objekte wurden später nachgerüstet.
Die Parameter Übergabe funktioniert über copy in/copy out, nicht über Referenzen.
Es ist eine sehr große Standardbibliothek dabei, die aber Unterteilt ist in Teilmengen für Embedded Systeme und für Arbeitsplatzrechner.
Die Sprache ist extrem Umfangreich. Es ist fast unmögliche den ganzen Sprachumfang zu kennen.
Als die Sprache Ada Mitte der 80er an Universitäten eingeführt wurde, gab es mehrere Probleme:
– die Größe des Sprachumfang machte die ersten Implementierungen problematisch und buggy.
– die Sprache galt als Kind des Militärs, und kurz nach dem Nato Doppelbeschluß wollten viele nichts damit zu tun haben.
– die ersten Implementierungen liefen so gerade eben auf den verfügbaren Rechnern.
– Abstürze im Ada System haben regelmäßig einen Reboot des Rechners notwendig gemacht. Das will man auf ’ner VAX nicht. Auf die IBM 370 haben Sie meines Wissens an der Uni kein Ada draufgelassen. Das Ada auf den ersten Workstations hatte Alpha Status, so daß die Workstations primär für C verwendet wurden.
Ich persönlich war damals von Ada schwer enttäuscht.
Mir fehlten:
– Stringverarbeitung (ich will mich nicht um die Details kümmern, das kann der Rechner mir abnehmen.)
– Garbage collection für allgemeine Heap Objekte
– die Möglichkeit etwas größeres als skalare Objekte als Ergebnis einer Funktion zurückzugeben.
Für mich waren damals Algol68 und Lisp das Maß der Dinge.
@Pragmatiker: Natürlich ist der Artikel alt, aber das ganze geht ja auf noch ältere Artikel zurück. Am Anfang steht da wahrscheinlich der von Brian W. Kernighan: „Why Pascal is Not My Favorite Programming Language“ von 1981.
Und was JavaScript angeht, so würde ich sagen, kann man sich damit genauso leicht und kräftig ins Knie schiessen, wie mit C bzw. C . Freilich, wenn man alle Möglichkeiten hat, kann man wählen, welche für die Lösung eines Problems die geeignetste ist. Aber das ist doch genau der Knackpunkt. Denn um wirklich wählen zu können, vor allem wenn es um Konzepte geht, sollte man diese auch verstanden haben. Aber gerade das scheint ja oft nicht der Fall zu sein, so das Konzepte vermischt werden die eigentlich getrennt bleiben sollten. Und damit wird dann das Chaos beschworen, das es eigentlich zu vermeiden gilt.
@Andreas Buschmann: Danke für die Info, das ist doch schon mal ein Anfang. Ich hoffe, es haben auch andere noch was dazu zu berichten.
@Hans: Ich stimme zu. Man kann in JavaScript nur vernuenftig programmieren, wenn man generell vernuenftig programmieren kann. Aber gilt das nicht fuer jede Programmiersprache? 😉
@Pragmatiker: Nun ja, für einige mehr als für andere. Pascal zwingt einen ja zu bestimmten Dingen, wie z.B. Typensicherheit. In Basic und anderen Sprachen wird die bekanntlich eher lax gehandhabt. Aber sonst brauchen wir das Thema auch nicht weiter zu vertiefen, weil ich denke, dass wir beide darüber Bescheid wissen.
Problematisch ist dann eher die Ausbildung der Programmierer. In einem C/C Programmierforum sieht man öfter mal Anfängerfragen von Leuten, die angeblich C lernen sollen, dann aber printf im Quelltext stehen haben anstatt cout, und die Ausbilder das Konzept der Objektorientierung anscheinend selbst nicht verstanden haben. Aber das ist ein Thema für sich und hat mit dem Thema hier nichts mehr zu tun.
An dieser Stelle ist C-plus-plus gemeint, also müsste der Satz so aussehen: „In einem C/Cpp Programmierforum sieht man öfter mal Anfängerfragen von Leuten, die angeblich Cpp lernen sollen, … wobei die Pluszeichen durch die kleinen p’s ersetzt sind.
Echt lustig was hier so geschrieben wurde.
Zum einen, ja ich gebe es zu, ich nutze auch heute noch „C“ und das nicht mal mit Widerwillen. Warum, dass ist ganz einfach, ich schreibe z.B. ein Programm für eine NXP Cortex-M0 MCU. Das ist eine 32/16 Bit Microcontroller mit immerhin 30MHz ohne Waitstates.
Das muss sehr Hardwarenaher Code sein, weil er ja sehr direkt mit der Hardware Arbeitet.
Assembler gibt es von mir keine Zeile, worüber ich sehr froh bin. Die ARM Technologie ist zwar sehr effizient, aber die Assembler Codierung ist schlimmer als x86 und das war schon schrecklich.
Aber was will man den, „C“ ist über 40 Jahre alt, vielleicht hat mancher das vergessen oder weiß es nicht, damals kostete ein Byte RAM ca. ein DM und davon konnte man ein kg gutes Brot beim Bäcker kaufen.
Die CPUs hatten weniger MHz, wenn nicht sogar nur 100kHz. Vor dem Hintergrund konnte man keine Compiler schreiben die einem all das abgenommen hätten was heute benötigt wird.
Von daher ist das gemotze über „C“ einfach, oder sogar SEHR EINFACH, aber wenig hilfreich.
Warum heute noch C Verwendung findet?
Ganz einfach, es gibt immer noch sehr viele Programmierer die z.B. wie ich ab und an Code für eine kleine MCU schreibe. Gibs dafür eine Alternative? Ja, C , C#, sicher nicht.
Für große Applikationen macht sowohl C wie C keinen Sinn mehr, aber auf eine MCU mit 8kB RAM und 32kB Flash, sicherlich ja.
Vor allem wird in dem Artikel eines komplett Unterschlagen, die Programmiersprache kann unterstützend wirken, die eigentlichen Probleme haben fast nie damit zu tun, sondern mit schlechten Softwareentwicklern.
Ich glaube es war der ehemaliger Arbeitgeberpräsident der gesagt haben soll: Ein Spitzensoftwareentwickler ersetzt 50 (schlechtere) Programmierer. Ich kann ihm dabei nur zustimmen, ich hab viele schlechte und bessere erlebt aber nur ganz wenige Spitzenleute.
C und C sind sicher alt, aber sich werden vermutlich noch weitere 40 Jahre genutzt werden. Ich hoffe allerdings das dies nurnoch dort passiert wo es wirklich nötig ist, von mir aus als Superassembler, aber bitte nicht auf so einer Ebene wie modernen PCs.
Wie bei den Kommentaren zu den raketen stimmen deine eingestreuten fakten nicht:
C ist nicht 40 Jahre alt
RAM kostete vor 40 Jahren ungefähr 1 Pfennig/Byte nicht eine Mark
Schon 1966 gab es Rechner mit 10 MHz, vor 40 Jahren lag die Spitze bei 80 MHz
@Bernd: Ok, SRAM kostete noch ein paar Jahre früher ne Mark.
Es geht darum das ein Byte einfach früher wirklich wertvoll war, man konnte keinen nicht optimierten Code schreiben. Eine PDP11 hatte erstmal 64k und billig war die beileibe nicht.
Was denkst du den was dein Boss dir gesagt hätte, wenn du ne Speichererweiterung für 3000DM benötigt hättest und er deinen Code angeschaut hätte und festgestellt hätte das du immer 16 Bit für eine 1-Bit Information genutzt hättest?
Sorry, der hätte dich entweder gleich gefeuert, oder dich zur Putzkollone abgestellt.
Von Stellen wo nicht nur für eine Anwendung ein Rechner gekauft wurde, sondern hunderte von Geräten einen Prozessor brauchten, wäre sowas undenkbar gewesen.
Was die Taktfrequenz betrifft hast du nur für Workstation recht, ich hab in der Zeit vom Commodore 2001 mit Computern angefangen. 3,5kB, Supper!
Da war eine 6502 CPU drin siehe hier: http://de.wikipedia.org/wiki/PET_2001
Anfang unter 1MHz und mehrere Takte/Befehl.
wer Mewinung mit Fakten mischt bei dem müssen die Fakten stimmen. Schon jetzt geht es weiter mit den falschen behauptungen:
Der VC 20 ist keine 40 Jahre alt
er wurde auch nie in C programmiert, sondern in Assembler
C zog erst mit Unix und Windows in den PC Bereich ein, das war ab Mitte der achtziger Jahre.
Zudem implizierst Du dass man nur mit C platzsparenden Code erzeugen kann. Das stimmt aber nicht, wie z.B. turbo Pascal beweis, das damals auch alle C-compiler bei der Ausfürhungsgeschwindigkeit abhängte.
Sie schreiben: „Das verrückte ist, dass es einige Leute gibt, die so was lieben und die offensichtlich Einfluss haben … Wenn ich dran denke welche Probleme schon meine Studis mit einer Programmiersprache mit doppelten Airbags haben, ich wage nicht dran zu denken was passiert wenn die in C programmieren müssten…“
Ich gehöre zu den Verrückten die seit 1985 hauptberuflich mit C und später C++ unterwegs sind. Ich bin weder Cola-süchtig, noch ackere ich eine 100-Stunden-Woche und ich bin sozial-verträglich mit Frau und Kindern. Ihre Tiraden über C/C++ in Ehren, aber: früher gab es die Unterscheidung in System-Programmierer und Applikations-Programmierer. Ich gehöre zu Ersteren, ihre Studis zu Zweiteren. Es gibt Unterschiede, nicht zuletzt im Gehalt und welche Projekte man durchführen darf, z.B. verteilte, redundante Realzeit-Systeme.
Schöne Grüsse an die Warmduscher. Siehe auch Ed Post, „Real Programmers don’t use Pascal“.
Sie schreiben „Der Buffer-Overflow … Das Problem ist natürlich das so ein System wie magisch alle Freaks anzieht und die dann darauf aufbauend noch schlimmere entwickeln, wie z.B. C++ (C erweitert um die Unverständlichkeit und Komplexheit)“.
Wenn der Professor, welcher das Wohl und Wehe eines jungen Menschen, Student genannt, kontrolliert sagt, dann wird es schon stimmen, oder? Mein Betriebssystem-Prof in meinem Informatik-Studium war nicht so festgelegt. Übrigens zu Buffer-Overflow: Seit mindestens 1983 mit Einführung 4.2BSD ist der Zeiger/Größe (Pointer/Size) Doppelparameter in C dokumentiert. Es gibt mehr als genug C-Bibliotheks-Funktionen die mit Doppelparameter Buffer-Overflow verhindern wie fgets(), snprintf(), strncat(), usw. Aber das erzählt ein Prof der C nicht mag natürlich nicht seinen Studenten …
Und in C++ gibt es mit der String Klasse die „Gummihelm“ Version welche Sie so für ihre Studis wünschen.
Der deutsche Professor ist verbeamtet und fühlt sich als Oberlehrer. Wie bescheidener ist doch der US-amerikanische Kollege bei dem es keinen Status auf Lebenszeit gibt.