
Am Ende ist C doch am besten
« | 17 Dec 2023 | »So sehr ich meine Ausflüge ins ZIG Land liebe, so sehr freut es mich, wenn ich dann doch wieder in die C/C++ Welt zurück nach Hause kommen kann.
Denn dort ist es eben doch am schönsten, und Code am besten schreibbar.
Es gibt viele semantische und “optische” Gründe, warum moderne Sprachen wie
ZIG
dem klassischen C überlegen sind.
Doch wenn ich an mein Kernziel des GATE Projektes denke, wo die Unterstützung von möglichst vielen Zielplattformen oberstes Ziel ist, dann stelle ich fest, dass es eben nur in C und C++ möglich ist, hier effiziert voranzukommen.
Beispiel Makros
Ja, Makros waren oft wie eine Seuche in der IT Geschicht. Einmal davon befallen, wird ein Projekt schnell unwartbar. Unleserlich ist es dann sowieso schon.
Aus diesem Grund entschied man sich in ZIG, ohne Makros auszukommen.
Nun sehe ich mir die WinAPI mit ihrer ANSI- und Unicode Variante an und muss feststellen, dass man das nur mit Makros effizient gelöst bekommt, wenn man beide Varianten unterstützen will.
Ob man jetzt 8-bit oder 16-bit Strings erzeugen will, oder automatisch ein “A” oder “W” ans Ende eines Funktionsnamen schreibt, lässt sich über ein Makro “dynamisch” zusammenbauen, während man ohne Makros oft Code doppelt ausimplementieren muss.
(ZIG’s comptime
kann das zwar auch lösen, braucht aber mehr Codeaufwand
um Ziel zu kommen.)
Beispiel Nullpointer
Nullpointer sind der Grund für jede Menge Probleme und Abstürze.
In ZIG
sind solche Pointer erst mal verboten, dafür gibt es jedoch
Optional
s, die man immer explizit prüfen muss.
Das erzeugt wirklich sicheren Code.
Es kann aber auch kontraproduktiv sein, wenn die Sprache keine Möglichkeit
bereitstellt, dass man auf einen Zustand vertrauen kann.
Wenn C-Pointer permanent auf Null und Nicht-Null Inhalt geprüft werden müssen,
kann daraus kein effizienter Code entstehen.
Das kann man zwar innerhalb der eigenen Funktionen gut optimieren, doch
wenn es um Schnittstellen wie z.B.: Funktionspointer geht, wird das mühsam.
Wenn eine Schnittstellendefinition einen Pointer aus “Mandatory” definiert, dann darf bzw. muss man auch darauf vertrauen können, dass die Gegenseite es richtig macht.
Ein anderer Punkt wären dann Plattformen, die “Null” nicht als ungültig
definieren. In x86-16 und somit auch in DOS liegt an Adresse Null
die Interrupt-Vektor-Tabelle, und wer einen Debugger oder Code-Guard schreibt,
muss eben auch auf diese Adresse schreiben dürfen.
Fazit
Unabhängig von den tollen Verbesserungen, die neue Sprachen einführen,
verbauen sie durch Ihre Architektur aber manchmal auch die Möglichkeit,
auf speziellen Systemen korrekt zu funktionieren.
Das bedeutet wir verlieren somit den Support auf diesen Systemen und
verringern damit die Bandbreite der Zielplattformen.
C
hat daher ganz bewusst viele Bereiche als “undefiniert” eingestuft, damit
die Sprache für wirklich “alles” offen ist. Und ja, das bedeutet auch, dass
man sich in den Fuß schießen kann.
Aber wir würden ja auch nicht Messer weltweit abschaffen, nur weil es möglich
ist, sich damit umzubringen.
Die Flexibilität von C wird heute leider nicht mehr als Vorteil gesehen, sondern bei Fehlern immer als Nachteil ausgelegt.
Tatsächlich brauchen wir jedoch mehr Programmierer, die ihren Code verstehen. Auch wenn ich viele Features aus neuen Sprachen schätze, so kann man nicht alle Probleme lösen, indem man stets neue Programmiersprachen erfindet, die Bandbreiten nur durch Verbote einschränken.