Systemorientierte Programmiersprache Zig – einfacher und schneller als C

Von Dipl. Betriebswirt Otto Geißler 4 min Lesedauer

Anbieter zum Thema

Zig ist eine systemorientierte Allzweck-Sprache. Neben der System-Entwicklung eignet sie sich für das Programmieren im Embedded-Systems-Umfeld, das Schreiben von Games und viele Aufgaben, die normalerweise von höheren Sprachen erledigt werden. Welche Potenziale eröffnen sich damit?

Zig ist eine systemorientierte Sprache, die es einfacher machen möchte, sicheren und korrekten Code zu schreiben.
Zig ist eine systemorientierte Sprache, die es einfacher machen möchte, sicheren und korrekten Code zu schreiben.
(Bild: Ziglang.org)

Für die systemorientierte Entwicklung existieren mit C, C++, Rust und Go bereits einige etablierte Sprachen. Dazu gesellt sich seit gewisser Zeit auch Zig, die das Beste dieser Sprachen vereinen und eine optimierte Performance sowie verbesserte Zuverlässigkeit bieten soll. Zig möchte dabei das Erbe der Programmiersprache C antreten, die seit Jahrzehnten als Low-Level-Sprache der Wahl und als Standard gilt.

Zen von Zig

Im Mittelpunkt des Designs von Zig steht eine Philosophie, die den Anwender in den Mittelpunkt stellt, indem sie sich auf die Usability und intuitiven Funktionen konzentriert: das „Zen of Zig“. Dazu gehört, dass Zig die Einfachheit gegenüber einem Zuviel an Funktionen bevorzugt. Oftmals bietet Zig nur einen einzigen Weg, ein bestimmtes Problem zu lösen. Daraus resultiert jedoch eine Reihe von Vorteilen.

Zum Beispiel ist Zig in seiner Gesamtheit vergleichsweise einfach zu erlernen, so dass Entwickler und Entwicklerinnen schnell produktiv agieren können. Insbesondere erlaubt es Zig all jenen, die C bereits gut kennen, das wesentliche Konzept der Sprache leicht abzubilden. Aus diesem Grunde kann man sich Zig als eine Weiterentwicklung vorstellen, die zwar C ähnelt, dafür aber sicherer, weniger fehleranfällig und einfacher sein soll.

So unterscheidet sich Zig von den meisten anderen Sprachen durch seinen geringen Funktionsumfang. Den Entwicklern von Zig liegt dieses Ziel so am Herzen, dass Zig eine Zeit lang sogar keine for-Schleife mehr ermöglichte, was als unnötige syntaktische Ausarbeitung der bereits ausreichenden while-Schleife angesehen wurde.

Zig verfügt auch nicht über einen Präprozessor, versteckten Kontrollfluss und die Speicherzuweisung ist intuitiver gelöst als die von C. Damit wird C sogar im Hinblick auf die Leistung übertroffen. Zig weist auch keine Makros auf, ist aber dennoch leistungsstark genug, um komplexe Programme klar und ohne Wiederholungen darzustellen.

Zielsetzungen und Syntax

Zig ist eine sogenannte „nahe am Metall“-Sprache, da sie es Entwicklern ermöglicht, direkt mit dem Systemspeicher zu arbeiten. Das bedeutet, Code lässt sich maximal für seine Aufgabe optimieren. Eine direkte Speicherzuweisung ist ein gemeinsames Merkmal der C-Familie, Rust und anderen Low-Level-Systemsprachen.

Zig bietet ähnliche Funktionen, die jedoch auf verschiedene Weise verbessert wurden. Auf den ersten Blick wirken die Funktionen von Zig vielleicht nicht gerade umwerfend, aber in der Gesamtbetrachtung bietet die Sprache eine erstaunlich sicherere Plattform, die für Entwickler einfacher zu beherrschen und zu nutzen ist.

Zig ähnelt zwar in gewisser Weise dem Schreiben von C, verfügt jedoch über bessere Funktionen der Speichersicherheit im Debug-Modus. Es existieren moderne Funktionen wie defer und es kann beliebiger Code zur Kompilierungszeit über comptime ausgeführt werden. Die Sprache bietet überraschend wenige Schlüsselwörter und ist auch in dieser Hinsicht leichter zu erlernen als C++ oder Rust. Derzeit wird Zig unter anderem dafür verwendet, um die JavaScript-Laufzeitumgebung Bun.js als Alternative zu Node.js zu implementieren.

Speicherzuweisung

Als eine der wesentlichen Besonderheiten von Zig ist hervorzuheben, dass die Sprache zwar eine direkte Möglichkeit benötigt, um Speicher zu allokieren, aber kein direktes malloc-Keyword wie bei C und C++ bereitgestellt wird. Somit obliegt die Speicherzuweisung der Standard-Library und erfolgt über eine Anfrage an ein Allocator-Objekt.

Der Sinn dieses Ansatzes zur Speicherzuweisung besteht also darin, eine versteckte Speicherzuweisung zu vermeiden, weil dies zu verschiedenen Problemen führen kann. Zum Beispiel verhindern versteckte Allokationen die Wiederverwendbarkeit von Code, indem sie die Menge an Systemen, die ihn verwenden können, unnötig reduzieren. So gibt es Anwendungsfälle, in denen man sich darauf verlassen muss, dass Kontrollfluss und Funktionsaufrufe keine Nebeneffekte auf die Speicher-Allokation haben.

Geschwindigkeit und Sicherheit

Zig gilt als eine schnellere Plattform wie beispielsweise C. Dies geht zum Teil auf den datenorientierten Designansatz zurück, der zu leistungssteigernden Optimierungen in der Zig-Programmierung führt, die in anderen Sprachen nicht möglich wären. Der Denkansatz dahinter ist einfach erklärt: Je weniger Speicher berührt wird, desto weniger Druck wird auf die CPU ausgeübt.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

Ausgehend von dieser Tatsache konzentrierten sich die Entwickler von Zig darauf, das Speichervolumen der Objekte zu reduzieren, die im selbstgehosteten Compiler von Zig erstellt werden. Die logische Konsequenz: Im Compiler wird weniger Speicher verwendet und der Cache der CPU weniger belastet, wodurch der Code schneller wird und sich dadurch die Geschwindigkeit von Zig um bis zu 35 Prozent steigern lässt.

Diese Art der Optimierung wäre in Sprachen wie Rust nicht möglich. Eine der Kernkomponenten der Leistungssteigerung von Zig sind die „untagged unions“. Durch die Platzierung der Tags in einem separaten Array wird die Belastung des Caches verringert. Zum Beispiel in Rust können keine „untagged unions“ zum Einsatz kommen, ohne den Code unsicher zu machen.

Hier manifestiert sich also der Kompromiss in Rust: Schreibt der Anwender sicheren Code, der schneller ist, verliert er die Fähigkeit, die Hardware des Computers voll auszunutzen. Oder er schreibt eher unsicheren Code, aber mit voller Performance. Zig unterscheidet sich von Rust darin, dass die Sprache beides ermöglicht: Anwender können schnelleren Code schreiben, der durch Sicherheitsüberprüfungen bei nicht getaggten Unions sicher ist.

Bedingte Kompilierung

Für Zig kommt bedingte Kompilierung zum Einsatz, wodurch ein Präprozessor wie in C obsolet wird. Daher verfügt Zig nicht über Makros wie C und C++. Anstelle von Makros bestimmt der Compiler von Zig, welcher Code zur Kompilierungszeit ausgewertet werden kann.

(ID:49968962)