HOWTO · C
Das Schlüsselwort register in C
Erfahren Sie, wie der Speicherklassenbezeichner register in C funktioniert, einschließlich Deklarationen, Adressbeschränkungen, Zeigern und Geltungsbereich.
Auf dieser Seite
In C-Versionen, die es unterstützen, ist register ein Speicherklassenbezeichner, der traditionell als Hinweis gedacht war, dass ein Objekt von schnellem Zugriff profitieren könnte. Er garantiert weder die Ablage in einem CPU-Register noch ein schnelleres Programm. Der Compiler entscheidet, wie das Objekt implementiert wird. Die nachfolgend beschriebenen Regeln können von der C-Version abhängen, auf die Ihr Compiler eingestellt ist.
Überblick über das Schlüsselwort register in C
Der Speicherklassenbezeichner register geht auf ein älteres Optimierungsmodell zurück: Programmierer konnten häufig verwendete Objekte als Kandidaten für die Registerspeicherung kennzeichnen. Moderne Compiler treffen Optimierungsentscheidungen anhand des Programms und der Zielplattform. Der Bezeichner ist daher kein Leistungsversprechen. Verwenden Sie ihn nur, wenn Ihre Zielversion von C ihn unterstützt und die Sprachregeln zur Deklaration passen. Wenn Sie die Leistung verbessern möchten, messen Sie diese unabhängig davon.
Eine CPU verfügt nur über eine begrenzte Zahl von Registern. C verlangt jedoch nicht, dass gewöhnliche Objekte vor jeder Operation in ein Register geladen werden. Bei der Übersetzung und Optimierung kann der Compiler Werte in Registern, im Speicher oder an anderen Stellen halten. Der Quellcode kann sich nicht auf einen bestimmten physischen Speicherort verlassen. Warnt ein Compiler im gewählten Sprachmodus davor, dass register veraltet oder nicht unterstützt ist, prüfen Sie seine Dokumentation und die für das Projekt konfigurierte C-Version.
Das Schlüsselwort register in C verwenden
Das folgende vollständige Programm verwendet register für drei lokale Objekte und gibt ihre Werte aus. Das Beispiel lässt sich ausführen, aber seine Ausgabe wird hier nicht gezeigt.
#include <stdio.h>
int main(void) {
register char letter = 'S';
register double amount = 10.0;
register int count = 8;
printf("letter: %c\n", letter);
printf("amount: %.1f\n", amount);
printf("count: %d\n", count);
return 0;
}
Die Deklarationssyntax ist ansonsten vertraut: Setzen Sie register vor Typ und Bezeichner zu den Deklarationsspezifizierern. Das Beispiel verwendet feste Werte, damit Sie sich auf die Deklaration und die formatierte Ausgabe konzentrieren können. Ob der Compiler den historischen Hinweis auf Registerspeicherung berücksichtigt, ist eine Implementierungsentscheidung. Die Korrektheit des Programms darf nicht davon abhängen.
Die Adresse einer register-Variablen in C abrufen
In C-Versionen, die den Speicherklassenbezeichner register definieren, darf der Adressoperator & nicht auf ein mit register deklariertes Objekt angewendet werden. Diese Einschränkung gilt auch dann, wenn eine Implementierung den Wert des Objekts tatsächlich im Speicher hält. Es handelt sich um eine Sprachregel und nicht um eine Aussage darüber, ob ein physisches Register eine Adresse hat.
Die Deklaration register int item = 22; ist beispielsweise in einem kompatiblen Sprachmodus gültig, int *address = &item; verletzt jedoch die Einschränkung. Ein Compiler muss einen Verstoß gegen eine solche Einschränkung diagnostizieren. Wortlaut, Schweregrad und Format der Diagnose hängen allerdings von der Implementierung ab. Übernehmen Sie daher nicht die Diagnose eines anderen Compilers, als wäre sie eine garantierte Ausgabe.
register mit einer Zeigervariablen in C verwenden
In C-Versionen, die den Bezeichner unterstützen, kann auch ein Zeigerobjekt selbst mit register deklariert werden. Der Zeiger kann weiterhin die Adresse eines anderen Objekts speichern. Die Einschränkung betrifft das Abrufen der Adresse des Zeigerobjekts selbst. Auf int value = 15; kann beispielsweise register int *cursor = &value; folgen: cursor zeigt dann auf value, und *cursor greift auf die Ganzzahl zu, auf die er zeigt.
Diese Unterscheidung hilft beim Lesen von Code: &value liefert die Adresse des gewöhnlichen Objekts value. Mit &cursor würde dagegen versucht, die Adresse des register-Zeigerobjekts abzurufen, was durch dieselbe Einschränkung untersagt ist. Der Bezeichner verändert weder das Ziel eines Zeigers noch garantiert er, wo eines der beiden Objekte gespeichert wird. Wenn der Compiler die Deklaration ablehnt oder meldet, dass der Bezeichner nicht unterstützt wird, prüfen Sie den eingestellten Sprachmodus.
register mit anderen Speicherklassenbezeichnern in C verwenden
register ist selbst ein Speicherklassenbezeichner und kann daher in derselben Deklaration nicht mit einem weiteren Speicherklassenbezeichner kombiniert werden. Deklarationen wie auto register int value;, static register int value; und extern register int value; sind insbesondere in Sprachmodi, die register unterstützen, ungültige Kombinationen.
Ein Compiler diagnostiziert eine ungültige Kombination, doch seine Meldung ist nicht als fester Wortlaut standardisiert. Wählen Sie für eine gültige Deklaration den einen Speicherklassenbezeichner, der zur gewünschten Lebensdauer und zu den Regeln für die Bindung passt. Der Typ – in diesen Beispielen int – und Qualifizierer sind separate Bestandteile der Deklaration; sie machen zwei Speicherklassenbezeichner nicht miteinander vereinbar.
Geltungsbereich von register-Variablen in C
In C-Versionen, die den Bezeichner unterstützen, ist er für Objekte mit Block-Sichtbarkeit und für Funktionsparameter vorgesehen. Für ein Objekt auf Dateiebene ist er nicht zulässig. Ein Funktionsparameter kann zum Beispiel als int total(register int count) geschrieben werden. Innerhalb eines Funktionsrumpfs ist auch eine Deklaration mit Block-Sichtbarkeit wie register int count = 22; zulässig. Eine Deklaration auf Dateiebene wie register int count; verletzt die geltende Einschränkung und muss diagnostiziert werden.
„Lokale Variable“ ist deshalb eine unvollständige Beschreibung: Sie kann den zulässigen Fall eines Funktionsparameters verdecken. Sichtbarkeit und Speicherdauer hängen zusammen, sind aber nicht dasselbe. Der Speicherklassenbezeichner register verspricht nicht, dass ein Objekt in einem CPU-Register liegt, und macht es nicht außerhalb seines gewöhnlichen Geltungsbereichs sichtbar. Wenn Sie älteren Code pflegen, prüfen Sie die für das Projekt ausgewählte C-Version und den Compiler-Modus, bevor Sie sich auf solche Deklarationen verlassen.