Websalon

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)
-----------------------------------------------------------------------------