|
C - Eine Sprache - Ihre Programmierer
Irgendwann in seiner Laufbahn als Softwarepoet braucht man so etwas wie einen Umbruch aus den Kinderschuhen heraus in das Erwachsenenalter, in die Welt der Grossen. Fuer mich war dies der Umstieg von anderen Sprachen auf 'C'. Mit diesem Schritt habe ich lange gezoegert. Ich hatte bereits - aus meiner heutigen Sicht vielleicht ein Jahr zu frueh - die Endrunde im BWInf (Anm. der Red. BWInf = Bundeswettbewerb der Infortiker) erreicht, fuehlte mich von Wissen um Listen und Baeume unbelastet, und lebte gluecklich mit meiner Muttersprache BASIC, die ich fuer ernste Zwecke (der BWInf war einer) gegen PASCAL eintauschte. Zwar hatte man mir in meinem Computerclub, dem HMH, schon mehrmals nahegelegt, endlich auf eine vernuenftige Sprache umzusteigen, die da 'C' hiesse, um darin fuer meinen Club zu programmieren, aber der erste Versuch eines Programmes in 'C' war an einem boesartig jede meiner Zeilen mehrfach kommentierenden & monierenden Compiler gescheitert. Ich versuchte schrittweise, das Verhaeltnis von Fehlermeldung zu Sourcetext zu verringern, und tatsaechlich sanken bald die Fehlermeldungen vom Fuenffachen auf das Doppelte, um irgendwann gaenzlich zu verschwinden. Fiebrig erwartete ich das erste Lebenszeichen in der Sprache einer an- deren Welt, doch es blieb aus. Zweifelsohne aber lief mein Programm, es wollte geradezu gar nicht mehr aufhoeren zu laufen, und haette ich nicht in Ungeduld den Stecker gezogen, so wuerde es sicher heute noch laufen. 'C' ist in diesem Sinne eine phantastische Sprache, sie produziert keine Fehlermeldungen. War ich noch aus GfA-BASIC den Sprung in den Editor zur fehlerhaften Zeile und aus PASCAL an eine Warnbox gewoehnt, so machte mir 'C' den Unterschied zwischen Fehler und Fehlermeldung deutlich. Kurzum, die Motivation war verschwunden, ich zog mich schmollend wieder zu PASCAL zurueck. Irgendwann wurde der Druck der Tatsachen dann aber doch so hart, dass ich an einen Neubeginn dachte. Um mir neben dem oben genannten Druck noch weiteren zu verschaffen, gruendete ich an meiner Schule eine C-AG, die mich als Leiter zum Studium der Sprache zwang. Bevor ich am Ende dieses und in weiteren Beitraegen zu den Hoehen und Details der Sprache komme, seien zunaechst einige Bemerkungen gemacht, die mir, dem Anfaenger, der sich doch schon so weit waehnte, als er sein erstes 2000-Zeilen-Programm schrieb, sofort an 'C' auffielen: Zum aeusseren Erscheinungsbild der Sprache ist anzumerken, dass C sich um eine moeglichst reichhaltige Ausschoepfung des Zeichensatzpotentials bemueht. Muss der ADA- oder Fortran-Programmierer sich nach den Schnelldruckern des DoD (Department of Defense) richten und mit einem minimalen Subset des ASCII-Zeichensatzes auskommen, so fordern C-Phreaks von Haus aus mehr als Grossbuchstaben und eine Handvoll Sonderzeichen. Waehrend andere sich mit BEGIN & END die Finger wund tippen, hat der C-Phreak mit 'Klammer auf' und 'Klammer zu' die Arbeit bereits erledigt und blickt weise laechelnd zum Lispler hinueber, der auch in dieser Hinsicht aehnlich denkt, allerdings wohl nur, damit er schmutzige Dinge, wie acht Bloecke in einer Zeile zu beenden ( '))))))))'), wenigstens ueberhaupt in einer Zeile relativ unauffaellig realisieren kann. C-Phreaks widmen jeder Klammer liebevoll eine eigene Zeile; das verleiht dem Listing Uebersichtlichkeit und einen Hauch von Grosszuegigkeit, und taeuscht ueber die kryptische Kuerze der Sprache auf den ersten Blick hinweg. Gleiches gilt fuer Modulo-Bildung ('%'), Bit-Operationen ('|' & '&'), logische Verknuepfungen ('||' & '&&'), Negationen ('!'), De-/Inkrementier- und Peek-/ Poke-Befehle ('++', '--', '*' und nochmals '*') sowie fuer eine Menge anderer Befehle (z.B. if / else) und natuerlich selbstredend die Grundrechenarten. Generell kann man sagen, dass das Verhaeltnis von Sonderzeichen zu Buchstaben fuer den C-Phreak mit der wichtigste Bestandteil in seinem Bemuehen um grosses Prestige (bei den C-Phreaks, andere zaehlen fuer ihn ohnehin nicht) ist. An dies moegen die Erfinder von C gedacht haben, als sie die Unterschei- dung der Gross-/Kleinschreibung fuer C postulierten. Selbst Muesli- Fresser (vgl. 'Maylbox 2/88') wie Wirth scheuen sich in ihren und anderer Profs Bibeln (Algorithmen & Datenstr...) nicht, sich auf einen einzigen Buchstaben je Variable zu beschraenken. Bleiben Mueslifressern jedoch nur dafuer 26 Moeglichkeiten, so hat der C-Phreak doppelten Spielraum. C-Phreaks mit mathematischem Hintergrund finden schnell heraus, dass ihr Vorteil gegenueber Mueslifressern in Abhaengigkeit zur Anzahl der Buchstaben exponentiell steigt: lassen sich drei Buchstaben beim besten Willen nicht vermeiden, so koennen C-Phreaks bereits acht Variablennamen benuetzen, wo der Mueslifresser nur einen sieht. (Wer's noch nicht kapiert hat: 'aaa', 'aaA', 'aAa', 'aAA', usw.). C-Phreaks der BWInfler-Gattung verzichten jedoch oftmals (insbes. beim BWIinf) auf die Moeglichkeiten ihrer Sprache, teils, um die an bundesdeutschen Unis zu Mueslifressern herangebildeten Studenten, die ihre Aufgaben bewerten, nicht hoffnungslos zu ueberfordern, zum anderen, weil es ihnen Spass macht, Programme in 'C' zu schreiben, die die in oben genannter Muesli-Bibel aufgefuehrten Programme an Muesli deutlich uebertreffen, indem sie auf GOTOs verzichten (return und break geben ihnen ohnehin ausreichend Spielraum dafuer) und lange Variablennamen benutzen. Der BWInf 'C'-Phreak leidet naemlich sehr darunter, dass die angeblich 'echten' Informatiker oftmals 'C' in der Sprachenwelt so sehen, wie Anglistiker Cockney gegenueber Oxford-English einschaetzen. Er fuehlt sich deshalb in diesen Dingen einem besonderen Erfolgsdruck ausgesetzt, und fuehrt, waehrend Muesli-Fresser so hart wie moeglich an den Strukturregeln PASCALs vorbei programmieren, eine freiwillige Selbstkontrolle in Form von ANSI-C und anderes ein. Eines der unterhaltsameren Spiele der 'C'-Phreaks besteht im Decodieren von CCC (C-Compakt-Code). Der 'C'-Phreak benuetzt oefters ohne boesen Willen Konstrukte wie jenes: *s+=i++==m++; Fordert man dann Muesli von ihm, so schreibt er: IF (i=m) THEN s^:=Succ (s^); i:=Succ (i); m:=Succ (m); Der Muesli-Fresser moniert dann als erstes die Klammer um die IF-Kondition, die unser 'C'-Phreak aus Gewohnheit seinem ueblichen Bestreben nach Sourcetext-Kompaktheit entgegen leider doch gesetzt hat, muss dann allerdings den Seitenhieb einstecken, dass sein Kollege (ein etwas befremdlicher Begriff) dafuer mit jenen zwei Klammern ueber zeilenlange, hierarchische AND/OR-Komplex-Konditionen hinaus kommt. Denn die Liste der Prioritaeten in 'C' ist lang, sie reicht ueber dreizehn Stufen, und wer sie alle kennt, gehoert schon zu den Fortgeschrittenen, die man daran erkennt, dass sie ihren 'K&R', (Bibel der 'C'-Phreaks) schon fuer missionarische Zwecke verliehen haben. Zurueck zum Beispiel: Man erkennt in ihm bereits den Phreak der Gruppe 3 (10 Sonderzeichen auf 3 Buchstaben: 10/3 = 3.33...). Ein anderes Merkmal der Klassifizierung von 'C'-Phreaks (der Begriff Klassi- fizierung taeuscht allerdings ein gruppeninternes Konkurrenzdenken vor, das nicht auf Tatsachen beruht; 'C'-Phreaks bilden oftmals eher quasi-religioese Gemeinschaften) ist der Gastronomie verwandt. Was dem Muesli-Fresser sein umgedrehtes 'V'(Victory)-Symbol ('^', born to lose?), ist dem C-Phreak der '*'. Allerdings geniesst er ein uneingeschraenkt gutes Verhaeltnis zu diesem Symbol, waehrend Mueslifresser ihm vom Haus aus mit Misstrauen, ja Feindschaft gegenueberstehen. Das aeussert sich beispielsweise in der Verfahrenstechnik des 'Call by reference'. Der C-Phreak uebergibt der Prozedur den Zeiger auf eine Variable, indem er beim Aufruf dieser Variablen ein '&'-Symbol vorausstellt. Selbstverstaendlich meckert ANSI-C sofort, sollte er dies einmal vergessen. Er fuehrt sich so ins Bewusstsein, dass die Prozedur eine Schreibmoeglichkeit fuer diese Variable besitzt. Anders der Mueslifresser: Um den hautnahen Kontakt mit dem "Schmutz" zu umgehen, ist die Definition des Uebergabemechanismus ausschliesslich durch ein unscheinbares und nicht besonders Assoziationen mit Zeigern weckendes 'VAR' erfolgt, und zwar nur in der Definition der Prozedur. So suchen Mueslifresser bisweilen lange nach Fehlern durch ploetzlich ohne sichtbare Ursache veraenderten Variablenwerten und entdecken schliesslich erst in einer meterweit entfernten Prozedur das unscheinbare VAR als Ausloeser des Uebels. Dank der schier grenzenlosen Freiheit, die der 'C'-Phreak durch seine Sprache erhaelt, hat er sein gutes Verhaeltnis zu Zeigern aber erst nach einigen anfaenglichen Haerten (Bomben, Gurus und andere Abstuerze) erlangt. Die Vertrautheit fuehrt ihn dazu, die Liste, sonst das Schreckgespenst der Programmierer (Lispler mal ausgenommen), als natuerliches Konstrukt wie von Gott gegeben zu akzeptieren. Seine Handhabung erscheint ihm einfach, es gibt ihm ausserdem wieder mal das Gefuehl, mit dem Lispler, jenem Lieblingsverbuendeten (welche prozedurale Sprache hat schon einen objekt-orientierten Dialekt ('C++'), wer liebt ebenfalls Klammern, undeklarierte Funktionen, Return-Values, von denen niemand etwas wissen will, und andere Grausamkeiten ?!) etwas gemeinsam in der harten Welt der modernen Informatik zu haben. Der 'C'-Phreak sucht in einer geordneten Liste vom Typ 'Tliste' mit Namen 'li' nach Element 'a' folgendermassen: Tliste *p; /* Deklaration eines Zeigers p auf ein Listenelement */ for (p=li; p && p->value<a; p=p->next); /*Suche */ (Anmerkung fuer Unkundige: die Syntax der for-Schleife in 'C' sieht folgendermassen aus: for(Anweisung zu Schleifenbeginn; Kontinuitaetskriterium; Schleifenendbefehl)) Der Mueslifresser, fuer den Shortcut-Evaluation leider nicht Standard ist, muss geringfuegig umstaendlicher formulieren: p : ^Tliste; stop: BOOLEAN; BEGIN p:=li; REPEAT IF p<>NIL THEN IF p^.value<a THEN stop:=TRUE ELSE BEGIN stop:=FALSE; p:=p^.next; END ELSE stop:=TRUE; UNTIL stop; Voraussetzung dafuer ist allerdings, dass sein PASCAL-Dialekt Zeiger ueberhaupt kennt. Als Wirth seinen Fehler bemerkte und die Verbreitung des Virus PASCAL nicht mehr stoppen konnte, er sich in etlichen Hochschulrechner eingenistet hatte, unzaehlige Rechenstunden verschwendete und sogar die Koepfe der Profs zu uebernehmen begann, dachte er sich schnell statt eines Gegenbazillus etwas aus, mit dem sich dafuer Anfaellige noch schneller infizieren wuerden: Modula. Leider war auch das nicht das Wahre, und erst Modula 2 half ein wenig wieder, das Uebel auszumerzen, so z.B. fuer die Zweitsemestler der Uni Hamburg. Freilich aenderte das wenig an der Gesamtsituation, findige Programmierer hatten schon zahlreiche, bessere Mutationen erzeugt, die unter Bezeichnungen wie UCSD- und Turbo- auch auf kleine Rechner uebergriffen. Das Heer heutiger Muesli-Viren laesst sich heute kaum noch ueberschauen, wilde Sprachkonstrukte wie 'FindWorld' werden angehaengt, die dieser Sprache stehen wie ein Heckspoiler und ABS dem 2CV (Ente), einer Sprache, die C.A.R. Hoare (Erfinder von Quicksort & grosser Mueslifresser) gerade wegen ihrer kleinen Befehlsmenge einst pries (vgl. 'Der neue Turmbau zu Babel'). Lediglich BASIC kann wohl auf eine groessere Vielfalt und Inkompatibilitaet in den Dialekten verweisen. Der Virus wird wohl noch einige Zeit kursieren, bis er von Viren verdraengt wird, die dem Computer und seinem Programmier wenigstens einen Teil der Geschwindigkeit und des Ausdrucksvermoegens zu- rueckgeben, den er unter FORTRAN besass und C behaelt. Das obige Beispiel ist fuer den etwas besseren 'C'-Phreak schnell Standardformulierung, die wohlmoeglich im Praeprozessor definiert ist (den 'C' als so ziemlich einzige Programmiersprache standardmaessig hat). Dieser Programmierer gilt, seinem Zeigerverhalten gemaess, bereits als Ein-Sterne-Koch. Ich selber darf mich bereits zur naechsten Klasse zaehlen, derer der Zwei-Sterne-Koeche. Die Zeiger auf Zeigervariablen sind naemlich bereits auf der naechsten Schwierigkeitsstufe, dem Einfuegen in geordnete Listen, ausserordentlich hilfreich. Ein Beispiel: Tliste *p, **last; /* Diesmal mit einer 'Zwei-Sterne-Variablen': last */ /* li ist der Zeiger auf das erste Listenelement */ for (last=&li, p=li; p && p->val<a; p=p->next) /* Position suchen */ last=&p->next; if (p->value == a) return; /* Element ist schon in der Liste */ *last=malloc (sizeof (Tliste)); /* Sonst Speicher reservieren */ *last->next=p; /* Liste nach hinten verbinden */ *last->value=a; /* und neuen Wert einfuegen */ Da ich ohnehin 'Zwei-Sterne-Konstrukte' in Turbo-PASCAL nicht zustande brachte, glaube ich, allen die PASCAL-Code-Dekompression ersparen zu koennen. Wer so einen Algorithmus schon mal in einem Lehrbuch gesehen hat, maile doch bitte; ich weiss naemlich nicht, wie verbreitet diese Methode mit dem Zeiger auf die Schreibposition fuer das neu eingefuegte Element wirklich ist. Ich stiess auf ihn, als ich fuer ein Verwaltungsprogramm beim Einfuegen in Listen einen schnellen und knappen Algorithmus suchte. Ein von mir und vielen verehrter 'C'-Phreak, David Betz, der Autor des weit verbreiteten XLisp, hat in seinem Source-Text zu XLisp viele Konstrukte des Drei-Sterne-Types verwendet, so zahlreich, das man ihm durchaus auch eine der hoechsten Auszeichnungen, die des 4-Sterne-Programmieres, zusprechen kann. Als letztes in diesem Beitrag ein kleines Gute-Nacht-Raetsel: Welche beiden der folgenden sechs Sterne bilden eine Gruppe (im mathematischen Sinne, also Gruppe von Operatoren) ?: '**s*=*m**p;' Aufloesung (in Form der Muesli-Dekompression): s^^:=s^^ * m^ * p^; also der dritte und fuenfte. Autor: Hans Georg Zezschwitz (RedJack@mcshh) ----------------------------------------------------------------------------- |
[Contrib]
[Chalisti]
[05]
C - Eine Sprache - Ihre Programmierer