Wenn Freaks Programmiersprachen machen….
Der von Michael K. als Rätsel gestellte Aufsatz von Kerningham über Pascal zeigt recht deutlich, warum man eine Programmiersprache oder ein Betriebssystem nicht nutzen sollte, dass von einem Freak erstellt wurde. Man kann sicher einiges an Pascal kritisieren, wie praktisch an jeder Programmiersprache – man wird immer schlauer. Das Hauptproblem von Pascal ist, dass es als Lehrsprache konzipiert wurde. Vielleicht das natürlichste, das ein Uniprofessor tut, aber es ist im praktischen Einsatz Blödsinn. Es macht keinen Sinn Programmieren auf einer Sprache zu lernen und im Einsatz dann eine andere nutzen. So fehlen Pascal wichtige Funktionen in der Ein/Ausgabebibliothek und die Stringverwaltung ist auch ziemlich schlecht implementiert.
Viele Punkte in dem Memo zeigen aber etwas anderes, nämlich die Grundeinstellung die Kerningham hat und die sich in C und Unix wiederfindet. Nämlich das man als Programmierer grenzenlose Freiheit braucht. Nur dazu ein Beispiel: Er bemängelt dass man in Pascal keine Fliesskommazahl an eine Funktion übergeben kann die Integer Zahlen erwartet, wie dies in FORTRAN der Fall war.
FORTRAN hatte nur formale Parameter als Platzhalter, genauso wie der K&R Standard von C. Es gab keine Wertparameter. Bei einem Variablenparameter wird aber die Adresse des Parameters übergeben. Welchen Sinn soll es nun machen, eine Fließkommazahl an eine Funktion zu übergeben, welche die Information als Integer interpretiert – die interne Repräsentation ist schließlich eine andere. Von dem Problem des Überlaufs ganz zu schweigen.
Die Konzeption von C ist dann auch ein Rückschritt zu Pascal: grenzenlose Freiheit. An und für sich was tolles. Man muss sich nicht um Datentypen kümmern, kann direkt auf den Speicher zugreifen und mit der fehlenden Prüfung des Stacks bei Funktionen oder ob der Speicher bei Feldern / Strings ausreicht um den Inhalt aufnehmen kann man auch den Code des Programmes überschreiben – absichtlich oder eben als Sicherheitslücke, die allseits bekannten Buffer-Overflows.
Ein einfaches Beispiel ist die Möglichkeit eine Zuweisung in der if Anweisung durchzuführen. Das erlaubt es die Zuweisung eines Rückgabeparameters einer Funktion und den Test auf 0 (es gibt ja keine Booleschen Variablen in C) in einer Anweisung zu machen. Für dieses Ersparen von etwas Tipparbeit handelt man sich schwer auffindbare Fehler ein, wenn man eigentlich einen vergleich mit „==“ anstatt „=“ durchführen wollte.
Überhaupt scheinen die Designer von C und Unix der irrigen Ansicht zu folgen, dass die Hauptarbeit beim Programmieren das Eintippen ist. Mit der kurzen Schreibweise von C mit vielen Operatoren, den Klammern kann man sicher am Tag eine Minute Tipparbeit sparen – um dann Stunden nach einem Fehler aufgrund dieser kurzen Schreibweise zu suchen. Oder man spart eine Sekunde beim Tippen von „ls“ und darf dann eine Minute mal das Manual studieren, welche der zahllosen kryptischen Parameter gerade benötigt wird.
Sicherheit bedingt eine Einschränkung der Freiheit. Ein System das Parameter prüft lässt eben nicht grenzenlose Typkonvertierungen zu. Doch aus irgendeinem Grund gibt es eine ganze Reihe von Programmierern die sich von Systemen mit maximaler Freiheit aber auch maximaler Gefahr von Fehlern verbunden ist angezogen führen.
Ich muss sagen C hat mich nachhaltig beeindruckt. Bevor ich Softwaretechnik studiert habe habe ich ja schließlich auch schon programmiert in BASIC, Assembler und vor allem in Pascal. Als ich dann zum ersten Mal mit C zu tun habe fühlte ich mich in die Computersteinzeit zurückversetzt: Das soll also die tolle Programmiersprache sein in der jeder programmiert? fehlerträchtig, umständlich (so muss man bei Strings dauernd selbst kopieren oder speicher allokieren anstatt das es eine Bibliothek dafür gibt) und kryptisch.
Seitdem habe ich auch C++, Perl, Java und C# als Abkömmlinge dieser Sprache kennen gelernt. C++ und Perl sind noch schlimmer. Sprich unnötig kompliziert und umfangreich (C++) oder noch kryptischer (Perl). Java und C# haben weitgehend mit C gebrochen was die Fehlermöglichkeiten angeht. Viele Anleihen von Pascal und anderen Sprachen sind übernommen worden. Aber ich muss sagen C hat mich so weitgehend negativ beeindruckt, dass ich mich für die Sprachen auch nicht sehr erwärmen kann – die Syntax ist eben noch „C-Style“.
Wie wäre die Geschichte verlaufen, wenn Wirth anstatt nach Pascal noch weitere Lehrsprachen (Modula, Oberon) zu erfinden, Pascal verbessert hätte. eine vernünftige Stringverwaltung (nicht mit fixer Länge und 255 Byte Beschränkung) und definierte Prozeduren für Lowlevelzugriffe geschaffen hätte die dann herstellerspezifisch implementiert werden. Das verschaffte Turbo Pascal ja auch den Erfolg. es gäbe zumindest für den Anwender keine Probleme mit Viren, nicht dauernde Sicherheitsupdates etc.
Wirth hat gerade in Modula2 die Fehler vermieden, die er in Pascal machte.
Damit ließ sich astrein programmieren und der Code selber flüssig lesen/debuggen.
Als relativ intensiver C-Programmierer ist meine Meinung zweigeteilt (ich freue mich aber trotzdem, dass Du so einen Artikel schreibst und ich ihn kommentieren kann ;))
Natuerlich hast Du Recht wenn Du sagst, dass die Manipulation von Strings in C extrem umstaendlich ist. Ich muss es wissen, ich habe mal einen kompletten E-Shop als CGI programmiert, und zwar nicht in Perl o.ae., sondern in C (!!!).
Gut, das war dann zwar wirklich skalierbar (ich glaube nicht, dass die Ausfuehrungszeit mal ueber 0,001 Sekunden lag ;-)), aber ich habe den Code irgendwann in die Tonne gehauen, weil man das einfach nicht mehr erweitern konnte – zu kompliziert und umstaendlich.
Ein Zusatzproblem bei C-Strings ist auch noch, dass sie langsamer sind, als sie es eigentlich sein muessten. strlen() z.B. muss jedesmal den ganzen String durchlaufen, um nach dem NULL-Byte am Ende zu suchen, anstatt (wie in Pascal) die Laenge des Strings einfach am Anfang des Strings zu speichern.
Aber es gibt – um Deine Kritik etwas zu kritisieren 😉 – auch sehr sehr gute und umfangreiche String-Libraries, die man einfach in das Programm einlinken kann und somit sich dieser Sorgen entledigen kann.
Genauso ist es mit Arrays, Listen, Hashes etc. – dafuer kann man ja Libraries nehmen, die’s wie Sand am Meer gibt.
Die Freiheit, in C immer direkt mit dem Speicher zu arbeiten, hat schon eine grosse Bedeutung und mir macht das auch Spass. Wenn man vernuenftig C programmiert, laeuft dasselbe Projekt eben in der Mehrzahl der Faelle um ein Vielfaches schneller als in anderen Programmiersprachen, weil man eben so direkt und frei optimieren kann.
Das schlimmste, was einem in C passieren kann, ist, dass man tatsaechlich unvorsichtig mit Strings oder anderen Puffern umgeht und sie ueberschreibt – und sich das dann aber nicht in einem Sofortabsturz aeussert o.ae., sondern darin, dass ploetzlich ganz andere Programmteile, die scheinbar nichts mit dem Puffer zu tun haben, ganz seltsame Fehler haben, weil irgendwelche ganz anderen Variablen ploetzlich ueberschrieben werden.
Das hatte ich schon des oefteren und ich habe schon mehrfach Projekte deswegen einfach aufgegeben bzw. komplett neu geschrieben.
Gut, heute gibt es Valgrind… 😉
Wahrscheinlich war aber gerade diese Fehleranfälligkeit ein Grund dafür, sich intensiver mit den diversen Problemen zu beschäftigen, und deren Auswirkungen in der Praxis zu studieren…
C und schneller als andere Sprachen? Immer wieder behauptet, aber nur solange man sich nicht die Mühe macht das auch mal nachzuprüfen. Wer wirklich schnelle Programme schreiben will kommt auch heutzutage nicht um Assembler drumrum. Natürlich schreibt man nicht mehr das gesamte Programm in Assembler, die zeitkritischen Stellen reichen ja schon. Inline-Assembler gibt es sowohl in C als auch in Pascal. (Jedenfalls in jeder vernünftigen Implementierung)
Die Pascal-Strings lassen sich recht einfach erweitern, wenn die Stringlängen-Variable auf 16 oder 32 Bit aufgebohrt wird. Würde mich sehr wundern, wenn es das inzwischen nicht auch schon als Bibliothek gibt.
Übrigens kennt Delphi inzwischen auch die C-Strings.
Also ich habe mir schon gedacht, dass bald das Grundübel bei dem Vergleich von Programmiersprachen auftritt: was vergleicht man.
In meinen Augen kann man nur Standards vergleichen, nicht konkrete Implemtierungen die jeweils eigene Erweiterungen und Bibliotheken mitbringen. Also in diesem falle den Wirth Pascal Standard und den ersten C-Standard von K&R. Ansonsten ist es unsinnig.
Man könnte da noch mehr sagen. Es gab dazu mal eine gute Website „C Hasser in 10 Tagen“, die leider inzwischen offline ist.
zur Geschwindigkeit: Ich denke das ist ein Mhytos. Es kommt immer auf die konkrete Implementierung einer Sprache an. Bei proceduralen Sprachen wie C und Pascal die vom Sprachkonzept vergleichbar sind denke ich werden gute Compiler gleich schnelle Programme hinbekommen.
Je nach Compiler ist dann mal die eine oder die andere Sprache besser. Ich weiss noch das zu DOS-Zeiten lange Zeit Turbo Pascal schneller als die meisten C-Compiler war. Bis heute wird neue Software für Berechnungen in FORTRAN geschrieben, weil es für diesen Zweig gute Compiler gibt.
Niemand hindert einen Compilerbauer daran aus der Anweisung „i:=i 1“ ein
inc ax
zu machen
anstatt ein
add ax,1
Das der Programmierer das bei C explizit schreiben muss zeigt eher wie faul die Sprachschöpfer waren….
C ist ja praktisch ein portabler Assembler. Seine Sprachelemente und Standardbibliotheken sind so primitiv, dass es fast nicht ueber die Faehigkeiten eines Makro-Assemblers hinauskommt.
Als Beispiel fuer die Geschwindigkeit: Dadurch, dass man staendig direkt mit dem Speicher rumeiert, weiss man ganz genau, was passiert und kann die auszufuehrenden Befehle auf genau das notwendigste beschraenken.
Ich nehme mal das Beispiel String-Manipulation und die Aufgabe: „Nehme einen leeren String und haenge in einer Schleife 1.000.000 Mal den aktuellen Wert einer Integer-Variable hintereinander dran, durch Komma getrennt“.
Erklaerung: sprintf() liefert als Return-value die Laenge des Strings, den es erzeugt hat. Den kann man einfach auf den „Hilfspointer“ p draufaddieren und muss somit fuer den naechsten Schleifendurchlauf nicht mehr die aktuelle Laenge des Strings finden (es leben Pointer! :-))
Ich wage zu behaupten, dass in jeder anderen Sprache das Kompilat langsamer sein wird als das eines C-Compilers, egal, wie man sich wendet und dreht.
Bernd: Dein Blog hat ein „plusplus“ verschluckt (der dritte Parameter in der for-Schleife muss aplusplus sein und nicht a)…
P.S.: Ich bezog mich auf das Kompilat dieses konkreten Beispiels, nicht allgemein.
Das Beispiel zeigt natuerlich deutlich, dass man C dann auch wirklich beherrschen muss und logisch denken koennen muss, um optimale Programme zu erzeugen.
Ich habe in einem bekannten Open-Source-Projekt dasselbe auch mal in dieser Form gesehen, und das ist dann natuerlich langsamer als BASIC, weil der Programmierer keine Ahnung hatte:
Das ist dann natuerlich katastrophal 🙂
… mal abgesehen davon, dass der mit calloc allokierte Platz in beiden Beispielen nicht ausreicht, da die Variable a wohl mehr als 1 Byte in der dezimalen Repräsentation lang sein wird….
Wie nennt man das ganze noch mal:
„Buffer-overflow, diese Sicherheitslücke wird ihnen präsentiert mit freundlicher Unterstützung durch die Sprache C“
zitat aus C-Hasser in 10 Tagen
http://www.parallelnetz.de/CHater.html
Sorry Bernd, hatte eine 0 zu wenig im calloc 🙂 PEINLICH 🙂
Übrigens: formatierten Code (ich habe die Posts selbst nachbearbeitet) kann man mit dem Smarteditor einfügen.
der wurde natürlich in Delphi geschrieben….
@Bernd: Danke fuer die Nachformatierung.
Einen Code-Editor habe ich leider schon selbst, der ist allerdings in JavaScript geschrieben 😉
Die Codebeispiele:
Sehr interessant. Allerdings ist mir der Bufferoverflow auch gleich beim ersten ansehen aufgefallen.
Hab die Beispiele auch mal in ein Programm gepackt, durch einen Compiler gejagt, und die Laufzeiten verglichen. Dabei hat mein compiler übrigens die Syntax von calloc kritisiert: da fehlt ein Parameter.
Was die Laufzeit selbst angeht: Die erste Version brauchte 2 Sekunden, die zweite ist am laufen, während ich diesen Text hier tippe…
Einige Zeit später, – so ca. 10 Minuten, aber genau weis ich es nicht, weil ich nicht auf die Uhr geguckt habe: Hab das Programm mal abgebrochen, weil ich den Eindruck hatte, dass es hängen geblieben ist, und im Debugger untersucht, ob da nicht noch ein Haken ist, den ich übersehen habe. Hab aber keinen gefunden. Damit dennoch nicht mehr der Eindruck auftritt, dass das Programm hängen geblieben sein könnte, hab ich die zweite Version so erweitert, das es nach jeweils 100 Schleifendurchläufen ein # (Lattenkreuz) ausgibt. Jetzt läuft es wieder, während ich das hier am schreiben bin. Da ich mal wieder vergessen habe, den Ausgabepuffer des Programms zu verkleinern, kriege ich jetzt anstatt einer kontinuierlichen Ausgabe von Lattenkreuzen von Zeit zu Zeit mal einen ganzen Schwall davon ausgegeben. So’n sch****! – Aber noch mal neu starten will ich jetzt auch nicht mehr; die zusätzliche Abfrage verfälscht das Ergebniss sowieso schon genug.
Später:
Inzwischen war der Jahreswechsel. War eine halbe Stunde draussen, um mir die Feuerwerke in der Nachbarschaft anzusehen, wobei der Computer weiter lief. Das blöde Propgramm läuft immer noch. Laut Taskmanager hat es inzwischen den Leerlaufprozess an Rechenzeit überholt. Danach läuft es bereits zwei einhalb Stunden bei einer CPU-Auslastung von 90 bis 98 Prozent…
Noch später:
Laut Taskmanager läuft dieses blöde Programm jetzt seit 4 Stunden 40 Minuten, was die reine CPU-Zeit angeht. Ich glaube, ich kann da noch bis morgen mittag warten, bis es fertig ist. (Zur Zeit, wo diese Zeilen entstehen ist es 3 Uhr 16.) Da ich keine Lust mehr habe zu warten, bis das Programm durch ist, bevor ich diesen Text online bringe, lasse ich die Kiste einfach mal laufen, während ich mich ins Bett haue. Das Endergebniss liefere ich dann nach, falls es überhaupt noch jemanden interessiert.
Codeeditor:
Ich benutze oft die mitgelieferten Editoren, teste zur Zeit aber auch den Open Source Editor Notepad . Der ist zwar manchmal etwas eigenartig, aber bisher komm ich damit ganz gut zurecht, so das ich denke, dass ich den wohl öfter benutzen werde.
C-Hasser:
Hab mir den Anfang davon mal durch gelesen, den Rest dann nur Stichprobenweise angesehen. Interessant fand ich dabei, das dort auch auf Bernds Text zu C verwiesen wird.
Dann wird in dem Text unten auf einen Bericht über eine Studie vom Bundesforschungsministerium zur Qualität der Softwareentwicklung verwiesen. Nun ist die Studie allerdings von 2001. Da wäre es mal an der Zeit zu überprüfen, ob die Zustände sich in der Zwischenzeit geändert haben, oder ob da immer noch das gleiche Chaos vorherscht. Sehr Aufschlussreich ist auch der Text von Hermann Wacker, auf dem dort ebenfalls verwiesen wird. Einige Beispiele davon konnte ich so nachvollziehen, d.h. bei mir kam der gleiche Müll heraus.
Allerdings haben die Texte alle eine gemeinsame Schwäche: Sie werfen C und C in den gleichen Topf und das sollte man nicht tun. Zwar hat C viele Macken von C geerbt, aber die OO Konzepte aus C gibt es in K&R C nun mal nicht. Und deshalb zeugt es von Unverständnis oder mangelhafter Differentierung, wenn man beispielsweise einschlechtes Klassenkonzept an C kritisiert. Das ist wie ein Vergleich von Äpfel mit Birnen, weil es in C keine Klassen gibt. Klassen sind ein Bestandteil des Konzepts der Objektorientierung aus C , aber nicht aus C.
Soweit erst mal. Ich hab auch noch einen Text in der Pipeline, wo ich mich über C und Pascal auslasse, d.h. meine Sichtweise über die Unterschiede. Der ist zur Zeit 4596 Byte lang, könnte aber auch noch länger werden…
@Hans: Wie die eingefügten Codebeispiele beweisen geht HTML auch sehr gut hier beim bloggen (zu deiner tabelle im letzten Eintrag). Vielleicht probierst Du es mal mit < table > oder mit < pre >
Mensch Bernd, wieso schluckt Dein Blog denn staendig plus-Zeichen? Hans wollte Cplusplus schreiben und es kam C raus, das ist gefaehrlich… soll ich Dir meine Blog-Software installieren?? 😉 (Nein, der Import der ganzen alten Artikel und Kommentare waere vermutlich zu viel Arbeit…)
@Hans: Achtung, in einem der beiden Programmschnipsel ist ein „Uebertragungsfehler“, und zwar im chronologisch aelteren: Da steht p gleich sprintf, es muss aber p plusgleich sprintf heissen… (traurig, dass man im Jahre 2010 noch Zeichen durch Buchstabencode ersetzen muss wie damals im Morse-Alphabet ;-)) Spielt aber fuer die Laufzeit keine Rolle, nur es haette so nicht funktioniert…
Dass das zweite Schnipsel um Groessenordnungen langsamer ist als das erste, wundert mich nicht. Er muss halt fuer jeden Schleifendurchlauf eine zweite Schleife ausfuehren, die den String bis zum Ende parsed (strcat()), was beim ersten Schnipsel vermieden wird, da das Programm selbst darueber „Buch fuehrt“, wo der String gerade zu ende ist.
Sorry wegen dem calloc-Fehler… passiert mir jedes Mal, ich hab auch den Sinn des zweiten Parameters nie verstanden 🙂
Ich weiss nicht ob plusplus als Simley Zeichen angesehen wird, aber es gibt ja noch das < pre > tag…
OK Bernd, dann werde ich ab jetzt auf Nummer sicher gehen und immer das Pre-Tag nehmen, wenn ich C- oder C -Code eingebe 😉
(Leider hilft das, wie man sieht, auch nicht ;))
Also ich finde WordPress klasse. Es ist so intelligent das es C plus plus auf C reduziert. Aus einer absolut schlimmen eine nicht ganz so schlimmen Sprache macht. Noch besser wäre natürlich wenn es automatisch aus „C“ Delphi machen würde – wer hätte das gedacht ein Blogsystem das schlechte Programmiersprachen nicht mag….
@Alexander: Das da bei dem sprintf plusgleich stehen muss, hab ich auch gemerkt. Dass die Blogsoftware allerdings die beiden Pluszeichen an manchen Stellen in meinem Text verschluckt hat, ist mir auch erst eben aufgefallen, nachdem ich Eure Kommentare gelesen habe.
Das Programm ist inzwischen übrigens fertig geworden, und meldete eine Laufzeit von 42811 Sekunden für die zweite Version. Wenn man das umrechnet, kommt man auf 13 Stunden, 16 Minuten und 51 Sekunden. Ich hab irgendwann mal angefangen, zwischendurch Screenshots vom Taskmanager zu machen. Der zeigte beim letzten Bild eine CPU-Zeit von etwas über 10 Stunden an. Dadurch ist das Programm ein schönes Beispiel dafür geworden, wie unzuverlässig die Zeitmessung mit clock() ist. Denn die Differenz zwischen dem, was das Programm selbst angezeigt hat und der letzten Info vom Taskmanager dürfte bei etwa 2 Stunden plus ein paar Minuten liegen. Genau kann ich das nicht sagen, weil ich nicht dabei war, als es fertig wurde. – Man könnte jetzt zwar noch mit WinAPI-Funktionen was ähnliches machen, aber dazu hab ich in diesem Fall keine Lust. Werde aber trotzdem mal nach solchen Funktionen gucken. Geben muss es die ja, weil der Taskmanager sie ja benutzt. Ansonsten würde mich interessieren, ob und wenn ja, wie man die ungefähren Laufzeiten solcher Funktionen im Vorfeld ermitteln kann.
@Bernd: Anscheinend akzeptiert WordPress nur eine bestimmte Auswahl an HTML-Tags, die auch von den Gästen des Blocks benutzt werden können, die Beiträge kommentieren wollen. Ich hab die Tabelle nämlich ursprünglich mit gebaut. Zum Vergleich hab Dir mal die Dateien mit meinen letzten Einträgen per email geschickt, u.a. den mit der Tabelle.
Ausserdem ist da noch der letzte Screenshot vom Taskmanager dabei, der die Laufzeit des Testprogramms anzeigt, sowie das Testprogramm selbst, falls das jemanden interessieren sollte. 😉
Okay, da Hans sich die Mühe gemacht hat das nachzuprüfen und ja mal die frage aufkam wie effizient die Sprachen sind: Hier die umsetzung in Delphi
Ausführungszeit auf einem Athlon 5050e (2×2,6 GHz): 0,3 s
Mei… – da muss ich ja mal wieder Delphi installieren, um zu sehen wie schnell das bei mir läuft… 🙂
Bernd: Schick ihm die EXE 🙂
Ach was, das ist nicht nötig! – Ich kann den Quelltext auch selber durch den Compiler jagen.
Also, für alle interessierten: 😉
Das Programm von Bernd gibt auf meinem AMD K6-II 300 MHz 6.20899996720254E 0000 aus. D.h. es braucht 6,21 Sekunden. Das ist zwar immer noch 3 mal so lange wie Alexanders erste C-Variante, aber dennoch sehr schnell.
.
.
Noch was anderes: In dem Text zu den C-Hassern sind einige Links zu anderen Kritikern, die teilweise grosse Fans von Ada sind. Daher die Frage, ob hier auch jemand Erfahrungen damit hat, und ob es sich lohnt, sich damit zu beschäftigen? – Einen Compiler hätte ich sogar. Es gab da nämlich mal ein nettes Buch mit dem Titel „Das Compiler-Buch“ von Heinz-Gerd Küsters (mitp-Verlag 2001, ISBN 3-8266-0659-0) wovon ich auch ein Exemplar besitze. Auf der zugehörigen CD ist u.a. auch eine Ada IDE drauf, und eine kurze Einführung (20 Seiten) im Buch.
Ich weis von Ada bisher eigentlich nur das es die obligatorische Sprache des Pentagons, also des US-Verteidigungsministeriums ist, das all seine Applikationen in Ada geschrieben haben will. Deshalb stellt sich mir auch die Frage, ob das nicht evtl. totes Wissen wäre. Denn ich bin mir nicht sicher, das ich in diesem Leben mal einen Job bekomme, wo man mich an sicherheitskritischen Applikationen mitarbeiten lässt, bei denen Ada auch gern eingesetz wird, wie ich beim lesen der C-Kritiker erfahren habe.
Hans: Danke fuer die ausfuehrlichen Tests 😉
Ich muss sagen, ehrlich gesagt bin ich wirklich erstaunt, dass die Pascal-Variante „nur“ 3 mal so langsam ist wie die C-Version. Hut ab (keine Ironie). Wobei sie ja noch keine Kommas setzt… vielleicht sollte man das noch einbauen und nochmal messen.
Ich bleibe aber trotzdem bei C – ich bin eben tatsaechlich schreibfaul und so’n bisschen „elitaer“ 😉
Die meisten Sachen, die ich heute programmiere, sind aber sowieso Web-Anwendungen und somit in Javascript und ’n bisschen PHP…
Das Programm kann man sicher optimieren, es gibt einige Routinen in Delphi um Zahlen zu konvertieren und ich habe nur die einfachste ausgesucht. Als ich übrigens in der ersten Version Floattostr genommen habe, also die Konvertierung einer fliesskommazahl war es auch erheblich schneller. Macht keinen Sinn, aber gut ….
Fragt sich wie realistisch dieses Beispiel ist. Hier ist ja die Stringlänge vorher bekannt, es ist also nicht nötig die Stringlänge zu ermitteln um zu sehen ob der Zielstring ausreicht. Bei praktischen Anwendungen ist aber genau das nötig, um arge Sicherheitsprobleme zu vermeiden. Und dafür jedes Mal den gesamten String abklappern zu müssen macht die Sache recht langsam.
Damit wurde nur gezeigt, daß mit unsauberer Programmierung ein Programm schneller werden kann. Wie zuverlässig das in realen Anwendungen funktioniert ist dann schon wieder eine andere Frage.
Elendsoft: Naja. Heutige Rechner haben so viel Speicher, dass es praktisch unmoeglich ist, ihn vollzubekommen. Und anstatt kleinkraemerisch nur 10 Byte zu allokieren und dann jedes Mal, wenn man merkt, dass der String zu lang wird, wieder 10 Byte dazu-zu-allokieren, nimmt man lieber von vornherein viel zu viel Speicher (der vom System oft eh nicht wirklich bereitgestellt wird und somit keinen Performance-Nachteil bedeutet), und gibt den restlichen dann hinterher wieder frei. Das ist eigentlich normale Programmier-Praxis…
Und gerade das ist ja ein Vorteil von C… ich kann selber genau entscheiden, was das System macht und wie… haette Bernd sein Beispiel mit „normalen“ Delphi-String-Routinen gemacht (er hat ja geschummelt, indem er per Hand eine Schleife programmiert hat, die Zeichen fuer Zeichen arbeitet) und sowas wie ’s plusgleich inttostr(a)‘, waere es wahrscheinlich wesentlich langsamer, weil Pascal dann wirklich staendig nachallokieren wuerde 🙂
Bernd: Vermutlich ist es mit der Float-Funktion schneller, weil die eine integrierte Funktion der FPU benutzt, waehrend diese inttostr vermutlich „handgecodet“ ist (in der Standard Library von Delpi)
Ich habe das Programm das Hans mir schickte auch mal laufen lassen und beim Delphi Programm wieder auf floattostr geändert. Resultat:
Delphi 0,325 s
Borland C 0,484 s
womit das längere Delphiprogramm schneller wäre. Aber dazu gibt es noch einen Blog der folgt.
Ein Blog? Nicht, dass C Dein zweites SpaceX wird 😉
Nicht gleich – die Blogs für die nächsten Tage sind schon fertig und über C habe ich mich schon auf der Homepage ausgelassen. Aber über Programmiersprachen allgemein und „schnelle Programme“….
Bin gespannt und werde natuerlich auch ordentlich meinen Senf zum besten geben 🙂
> Hans: Danke fuer die ausfuehrlichen Tests 😉
Bitte sehr.
Nun ist Borland ja aber auch dafür bekannt, sehr schnellen Code zu erzeugen. Die berühmten Compiler aus den 80er und 90er Jahren hatten den Vorsatz „Turbo“ ja nicht umsonst gehabt.
Zu den Laufzeiten: Irgendwie scheint aber auch diese Variante von Bernd davon abzuhängen, wieviele Prozesse da noch im Hintergrund laufen. Ich hab die gerade noch um das Komma im String erweitert und noch mal laufen lassen. Diesmal brauchte sie nur 5,9 Sekunden, war also um etwa 3 Zehntel schneller als gestern.
@Elendsoft: Die Argumente sind sicher richtig, aber dem kann man ja abhelfen, indem man sich seine eigene Stringverarbeitung baut, wo dann zu jedem String auch separat die Länge verwaltet wird.
Nun kenn ich mich mit Cplusplus nicht wirklich aus, kann mir aber vorstellen, das es in dessen Stringklassen sowas gibt. D.h. Eine Verwaltung der Längeninformation eines Strings, wie es sie in Pascal auch gibt.
Alexander schreibt:
> Elendsoft: Naja. Heutige Rechner haben so viel Speicher, dass
> es praktisch unmoeglich ist, ihn vollzubekommen.
Da wär ich mir nicht so sicher. Wer es drauf anlegt, schafft das auch. 😉
Und was die Schleife von Bernd angeht: Da hat er doch den selben Trick angewandt, der auch die C-Version so schnell macht.
Floattostr vs. InttoStr
Da müsste man wahrscheinlich mal in den Assemblercode gucken, um heraus zu finden, warum die Floatvariante schneller ist. Ich hab allerdings bei meiner Delphi-Version (Delphi6 Professional von einer PC-Magazin CD) noch keine Möglichkeit gefunden, um eine Assemblercode Datei (*.asm) erstellen zu lassen. Bei C Compilern gibt es dafür ja eine Option, ich hoffe in Delphi auch. Denn leider bin ich nicht so gut in PC-Assembler das ich die Info aus einer IDA-Analyse des Programms heraus fischen könnte. 🙁 (Obwohl IDA-Pro ein geniales Programm ist.)
Auf den Blogbeitrag zu den „schnellen Programmen“ bin ich auch gespannt.
Und zum Schluss wäre noch festzustellen, dass Ihr alle meine Frage bezüglich Ada in meinem letzten Kommentar „übersehen“ habt …
Beim Debugger in die CPU Ansicht umschalten, wenn Du an der Stelle bist, dann hast Du den Assemblercode
Die borland Compiler sind leider nicht so toll modernisiert worden, wie andere. Ich denke sie erzeugen immer noch nur 386 Code, also nix mit SSE, etc. Sie fordern auch nur einen CPU Kern und nehmen keine 100% Prozessorlast, daher ist die Laufzeit davon abhängig was nebenher noch läuft (beim ersten Test waren es z.B. 0,3 anstatt 0.325 s, wenn der Mplayer wie üblich bei mir läuft sind es 0,379 s).
@Hans: Wie gesagt, es gibt schon zu Hauf String-Libraries fuer C (genau wie Linked-List-Libraries, Hash-Libraries, blablablabla), deshalb ist das nicht wirklich ein Problem und man muss auch nichts selber schreiben bzw. sollte es auch nicht, weil die vorhandenen Libraries wahrscheinlich von Leuten gemacht wurden, die sich damit besser auskennen und die optimiert sind 🙂
in Cplusplus gibt’s ja die STL (Standard Template Library), fuer C gibt es vergleichbares, nur eben ist es nicht „Standard“. Aber das ist ja nicht schlimm 🙂
@Bernd: Ah danke, das ist auch ’ne Möglichkeit um an den Assemblercode zu kommen. Ist zwar keine separate Datei, wie man es bei C machen kann, aber gut, so wichtig ist es in diesem Fall auch nicht.
Das die Borlandcompiler nicht so modernisiert wurden, wie es angebracht gewesen wäre, war dann vielleicht ein Grund dafür, das sie an Bedeutung verloren haben, spekulier ich jetzt einfach mal. Zumindest die „Turbo“ Compiler. Aber vermutlich war die komische Firmenpolitik in den 90er Jahren auch nicht gesund fürs Image. Egal, ist eh nicht mehr zu ändern.
@Alexander: Okay, dann hat man als Entwickler „bloss“ die Aufgabe, sich aus dem riesigen Angebot das heraus zu suchen, was den eigenen Wünschen am besten entgegen kommt. Das dürfte je nach Vorstellung / Zielsetzung aber auch eine recht umfangreiche Aufgabe sein.
Und was den Standard angeht, da hab ich in einem C/Cpp Forum schon anderes gelesen. – Aber okay, das war auch meisst an Anfänger gerichtet, die noch nicht wirklich durchgeblickt haben. Denen wollte man erst mal beibringen, das es den Standard überhaupt gibt und wozu der gut ist.
Der vom Compiler erzugte Assemblercode ist für einen Hochsprachenentwickler eigentlich nicht interessant. Das C das extra erzeugt ist eher eine Unart und bei keiner anderen Sprache so.
Warum Delphi so an Bedeutung verloren hat hat nichts mit den Compilern zu tun, das hat andere Ursachen die ich auch noch mal aufgreifen will.
Sagen wir mal so: Der vom Compiler erzeugte Assemblercode sollte für Hochsprachenentwickler eigentlich uninteressant sein. In den meissten Fällen ist er es wohl auch. Das C das so macht liegt wahrscheinlich in seiner Entstehungsgeschichte begründet, wonach die ersten C-Compiler grundsätzlich erst mal Assembler Quelltext erzeugt haben, der dann von einem separat zu startenden Assembler in den ausführbaren Maschienencode übersetzt wurde.
Und mich interessiert der von Compilern erzeugte Code deshalb, weil ich es als Hilfe (für Fortgeschrittene) zum Assembler lernen betrachte, wenn man den Code eines Compilers studiert. Ansonsten ist es natürlich nur für Compilerentwickler wichtig, weil die ja dafür sorgen sollen, das der Compiler richtig arbeitet.
Die Anzahl der Kommentare wird ja langsam rekordverdächtig, da muss ich dann auch noch mal meinen Senf dazugeben.
Der Assemblercode kann hilfreich sein, wenn man optimieren möchte, ohne gleich den Schritt zu handcodiertem Assemblercode zu machen. Das habe ich auch schon das eine oder andere Mal gemacht.
Ansonsten ist es schön, dass hier kein Glaubenskrieg ausgebrochen ist. Je nach Anwendung kann die eine oder andere Programmiersprache sinnvoller sein, und manchmal bleibt einem sowieso keine Wahl. Wer z.B. UI auf dem Mac programmieren will, kommt um Objective-C nicht herum (vielen Dank Apple…), und momentan programmiere ich Code, der sowohl auf PC, Mac und einer ARM-Plattform laufen muss. Da bleibt maximal die Wahl zwischen C und C Plusplus, einfach weil es keine anderen Compiler für alle 3 Plattformen gibt.