Nicht nur Hardware-, sondern auch Betriebssystem-Unabhängigkeit:

C ist mehr als ein Anhängsel von Unix

14.07.1989

Ursprünglich wurde C zur Programmierung unter dem Multiuser- und Multitasking-Betriebssystem Unix entworfen. Daher hat diese Sprache ihre Stärken im systemnahen Bereich und bei den Schnittstellen. Immer mehr wird sie jedoch auch im kommerziellen Bereich eingesetzt. Anton Illik* versucht. den Eigenschaften von C auf den Grund zu gehen.

*Anton Illik ist Geschäftsführer der Ambit Informatik GmbH Hohenbrunn

Die Industrie setzt die Sprache C hauptsächlich in der systemnahen Programmierung ein. Beim Bau von Assemblern, Compilern, Betriebssystemen, Programmierumgebungen und Testsystemen hat sie sich ebenso bewährt wie im Bereich der technisch-wissenschaftlichen Software (Graphik, Prozeßsteuerung, Simulation) und der hardwarenahen Mikroprozessor-Programmierung.

Durch die statische Notationsstruktur die Ablaufdynamik eines Programmes sichtbar zu machen, ist die zentrale Idee der strukturierten Programmierung. C ist eine formatfreie Sprache und bietet Kontrollstrukturen, um Wiederholungen und Verzweigungen ohne Sprünge programmieren zu können. Durch die Formatfreiheit ist der Programmtext nicht an bestimmte Spaltenpositionen gebunden, so daß der Programmierer geschachtelte Kontrollstrukturen - entsprechend der Idee der strukturierten Programmierung - frei einrücken kann. Daraus resultieren leicht lesbare Programmstrukturen, die Wartungsfreundlichkeit wird deutlich verbessert und Einarbeitungszeiten reduzieren sich.

Software Module werden mehrfach verwendet

Ein Programmsystem so aufzubauen, daß logisch Zusammengehörendes (Typdefinitionen, Datendefinition, Funktionsdefinitionen, Makrodefinitionen) in eigenen Quellcode-Modulen (Dateien) zusammengefaßt werden, um daraus bindefähige Objektcode-Module oder Bibliotheken zu machen, ist der Sinn der modularen Programmierung.

Das in der Sprachdefinition enthaltene Konzept der separaten Übersetzung einzelner Module ist so ausgelegt, daß es den Anforderungen des Software-Engineerings weitgehend entspricht: Für das Information-Hiding sind alle dazu notwendigen Sprachmittel vorhanden.

Fünf wesentliche Vorteile bietet die modulare Programmierung ihren Anwendern:

Erstens: Werden die Module in eine hierarchische Dateistruktur eingebettet, so lassen sich damit logische Abhängigkeiten zwischen den Systemteilen sehr gut zum Ausdruck bringen.

Zweitens: Es ergeben sich überschaubare Bearbeitungseinheiten. Das kommt der Effizienz des Programmierers zugute.

Drittens: Es lassen sich damit Module realisieren, die mehrfach verwendet werden können. Die Mehrfachverwendung kann innerhalb eines oder mehrerer Projekte erfolgen. Das arbeitsteilige Vorgehen erhöht die Effizienz des Teams.

Viertens: Hardwareabhängigkeiten lassen sich in definierten Modulen zusammenfassen. Damit werden Portierungsarbeiten vereinfacht.

Fünftens: Über Bibliotheksmodule läßt sich die Sprache C beliebig erweitern. Die selbstgeschriebenen Bibliotheksfunktionen sind genauso einfach zu verwenden wie die mit dem Compilerpaket standardmäßig mitgelieferten Funktionen. Auf dem Markt gibt es Dutzende von C-Bibliotheken mit allen möglichen Spezialfunktionen zu kaufen.

Der hohe Grad an sprachinhärenter Portabilität hat im wesentlichen

seine Ursache in der umfassenden Sprachdefinition. Der Leistungsumfang ist ein weiterer Grund, warum die Sprachdefinition (ursprünglich von Brian W. Kernighan und Dennis M. Ritchie, später durch den ANSI Standard X3J11) akzeptiert wurde. Außerdem: Es gibt praktisch keine Dialekte der Sprache.

Allerdings ist die Portabilität keine binäre Eigenschaft, die entweder vorhanden ist oder nicht. Die Eigenschaft "Portabilität" ist vielmehr ein Kontinuum: Von der hundertprozentigen Portabilität bis zur Unmöglichkeit einer Portierung sind die Zwischenstufen denkbar. Die Portabilität muß letztendlich ein Entwurfsziel sein, will man die Sicherheit haben, daß sich die geschriebene Applikation leicht zwischen Computern mit möglicherweise auch verschiedenen Betriebssystemen portieren läßt.

Defensive Programmierung erhöht die Laufsicherheit

Den Verzicht Kniffe und Tricks so zu programmieren, daß die resultierenden Programme hohen Sicherheitsanforderungen gerecht werden, bezeichnet man als defensiven Programmierstil. Die Sicherheit einer Sprache wird im wesentlichen bestimmt durch ihre Strukturierungseigenschaften einerseits und andererseits durch die Typstrenge. Wie gut die Strukturierungseigenschaften einer Sprache sind, läßt sich "messen" anhand der verfügbaren Kontroll- und Datenstrukturen. Mit Kontrollanweisungen, skalaren Datentypen, Kompositionstypen und der Möglichkeit, eigene Datentypen einzuführen, ist C reichlich ausgestattet.

Was die Typstrenge angeht, so bietet die Sprache eine Reihe von Variationsmöglichkeiten: Bei der Programmierung hardwarenaher Operationen ist es unerläßlich, die strenge Typisierung zu umgehen - C gestattet dies dem Programmierer auf einfache Weise, ohne daß er Kunstgriffe anwenden muß. Ist andererseits bei der Programmierung auf entsprechend hohem Abstraktionsniveau eine modulübergreifende, strenge Typisierung notwendig, so läßt sich auch dieses machen.

Weitere Kriterien die Rückschlüsse auf die Sicherheit zulassen, sind Qualität und Quantität der Operatoren. In dem Maße, wie die Anzahl der Operatoren zunimmt, sinkt die Notwendigkeit, fehlende Operatoren durch trickreiche Programmierung zu ersetzen.

Zu guter Letzt wird die Sicherheit eines Programms auch von seiner Lesbarkeit beeinflußt. Neben den von der Sprache angebotenen Strukturierungsmöglichkeiten prägt vor allem die Verwendung sprechender Namen die Lesbarkeit. Mit einer Länge von mindestens einunddreißig (gültigen) Zeichen für (interne) Namen sind hier dem Programmierer kaum Grenzen für eine aussagefähige Bezeichnungssystematik gesetzt.

Durch eine Reihe von Spracheigenschaften versucht C einen kompakten Programmierstil zu fördern: Der C-Programmierer muß im Vergleich mit den Anwendern anderer Hochsprachen (Ada, Basic, Cobol, Fortran, Modula-2, Pascal) weniger schreiben. Die Quellprogramme sind kürzer, ohne daß die Lesbarkeit leidet. Ursache für die Kompaktheit sind unter anderem die Sprachsymbole (so werden etwa für die Blockklammerung statt BEGIN und END die Symbole { und } verwendet), die mächtigen Operatoren (statt a = a + 5 notiert man a + = 5) und die Nutzungsmöglichkeiten von Seiteneffekten.

Programme auf hohem Abstraktionsniveau, ohne Berühungspunkt mit den Niederungen der Hardware lassen sich in C ebenso schreiben wie sehr hardwarenahe Routinen, um seinem Computer das Äußerste abzuverlangen. Mit Hilfe von Zeigern (Pointer) werden Speicherinhalte direkt bearbeitet.

Pascal bietet dem Programmierer zwar auch Zeiger an, jedoch sind die entsprechenden Sprachkonstrukte dort meines Erachtens nicht so einfach und leistungsfähig wie in C. Auch der direkte Speicherzugriff in Basic mit PEEK und POKE erreicht die Flexibilität der C-Pointer bei weitem nicht.

Register-Variablen als Schleifenzähler

Andere Maschinenressourcen, die sich nutzbringend einsetzen lassen, sind die freien CPU-Register. Um Schleifen mit maximaler Geschwindigkeit zu fahren, definiert der C-Programmierer Register-Variablen als Schleifenzähler. Damit werden Speicherzugriffe auf die Schleifenzähler vermieden und dadurch die Schleifengeschwindigkeiten erhöht.

Die folgende Tabelle gibt einen Anhalt über die Laufzeitunterschiede zwischen verschiedenen Sprachen. Selbstverständlich kann ein solcher Vergleich keine absolute Qualifizierung von Sprachen sein. Da aber Sprachen - unter dem Aspekt der Effizienz - nur so gut wie ihre Compiler sind, soll diese Tabelle dennoch vorgestellt werden.

Die Spannen in der Spalte "relative Laufzeit" machen deutlich, daß die Laufzeiteffizienz sehr stark von der Qualität des verwendeten Compilers

abhängt beziehungsweise von der Qualität des Optimierers.

Alle marktgängigen C-Compiler sind mit Optimierern ausgerüstet.

Dies sind in der Regel sogenannte lokale Optimierer oder Guckloch-Optimierer (peep hole optimizer) mit relativ beschränkten Möglichkeiten: Innerhalb einer Funktion werden Anweisungssequenzen optimiert. Bessere Möglichkeiten, mit einem höheren Optimierungsgrad bieten globale Optimierer, die mit Hilfe der Datenflußanalyse versuchen, eine Funktion insgesamt zu optimieren.

Portabilität sichert eine breite Marktbasis

Die bisher angesprochenen Eigenschaften der Sprache C spielen in allen Bereichen des industriellen Softwarebaus eine Rolle. Dem Hersteller von Standardpaketen dürfte die Portabilität am wichtigsten sein, denn er ist in aller Regel auf eine breite Marktbasis angewiesen. Es ist sicher eine gesunde Entscheidung, die Softwareinvestitionen nicht nur an die Marktpräsenz bestimmter Hersteller zu binden, sondern mit den vorhandenen Standardpaketen auf eine möglichst breite Hardwarepalette unterschiedlicher Computeranbieter zu zielen.

Im Industriebereich der auf Mikroprozessortechnik basierenden intelligenten Geräte steigen die Investitionen in die Mikroprozessor-Softwareentwicklung stetig. Um die Softwareinvestitionen zu schützen, müssen sich die Gerätebauer unter anderem durch den Einsatz einer geeigneten Programmiersprache die Unabhängigkeit vom Prozessorhersteller erhalten. Angesichts des raschen Wandels im Bereich der Prozessortechnik ist der Softwareentwickler darauf bedacht, selbst technologisch unabhängig zu bleiben. Es ist wirtschaftlich nicht vertretbar, bei einem Wechsel des Prozessors aufzugeben, weil die bereits vorhandenen Assembler-Programme nicht auf einen neuen Typ portiert werden können. Diese Gefahr besteht schon beim Prozessoraustausch innerhalb der Angebotspalette eines Herstellers und ist naturgemäß am größten, wenn mit dem Chip auch der Hersteller gewechselt wird. Die Möglichkeit, auch in Zukunft den Hersteller seiner Mikroprozessoren frei wählen zu können, kann für den Produzenten intelligenter Geräte überlebensnotwendig sein: Um im Wettbewerb die Nase vorne zu haben, ist es von entscheidender Bedeutung, technologisch führende Mikros einzusetzen, selbst dann, wenn sie nicht vom bisher bevorzugten Halbleiterhersteller produziert werden.

Aufgrund der Eigenschaften von C erscheint mir diese Sprache als ein mögliches Mittel, sich gegen die diskutierten Probleme zu schützen.

Eine interessante Perspektive für den C-Programmierer ist die Sprache C++. In den Jahren 1980 bis 1983 wurde die Sprache von Bjarne Stroustrup in den Bell-Laboratorien von AT&T entwickelt und befindet sich schon seit einiger Zeit im industriellen Einsatz: UNIX System V beispielsweise ist mit C++ geschrieben worden.

Die Sprache ist eine Weiterentwicklung von C und bietet eine Plattform für die objektorientierte Softwareentwicklung.

Kurze Einarbeitungszeiten durch Standardisierung

Obwohl C ursprünglich für das Betriebssystem UNIX entworfen wurde, ist die Sprache längst hardware- und betriebssystemunabhängig geworden. Auf der Grundlage des Standards X3J11 des American National Standards Institute (ANSI) ist C heute auf nahezu allen Betriebssystemen und Prozessoren verfügbar. Das bedeutet für den Programmierer, daß er mit seinem erworbenen C Wissen auf allen Computern und Betriebssystemen ohne lange Einarbeitungszeit kurzfristig produktiv werden kann.