Wie in dieser Frage besprochen, definiert GCC nicht standardmäßige unäre Operatoren &&
um die Adresse eines Etiketts zu übernehmen.
Warum wird ein neuer Operator definiert, anstatt die vorhandene Semantik von zu verwenden? &
Operator und/oder die Semantik von Funktionen (wobei foo
und &foo
beide liefern die Adresse der Funktion foo()
)?
Label-Namen stören andere Bezeichner nicht, da sie nur in Gotos verwendet werden. Eine Variable und ein Label können denselben Namen haben, und in Standard-C und C++ ist aus dem Kontext immer klar, was gemeint ist. Das ist also vollkommen gültig:
name:
int name;
name = 4; // refers to the variable
goto name; // refers to the label
Die Unterscheidung zwischen & und && wird daher benötigt, damit der Compiler weiß, welche Art von Namen zu erwarten ist:
&name; // refers to the variable
&&name; // refers to the label
GCC hat dies hinzugefügt Verlängerung zum Initialisieren eines statischen Arrays verwendet werden, das als Sprungtabelle dient:
static void *array[] = { &&foo, &&bar, &&hack };
Wo foo
, bar
und hack
sind Etiketten. Dann kann ein Label mit Indizierung wie folgt ausgewählt werden:
goto *array[i];
Standard sagt das
C11: 6.2.1 Gültigkeitsbereich von Identifikatoren (p1):
Ein Bezeichner kann eine bezeichnen Objekt; eine Funktion; ein Tag oder ein Mitglied einer Struktur, Vereinigung oder Aufzählung; ein Typedef-Name; a Markenname; ein Makroname; oder ein Makroparameter.
Weiter heißt es in Abschnitt 6.2.3:
Wenn an irgendeiner Stelle in einer Übersetzungseinheit mehr als eine Deklaration eines bestimmten Bezeichners sichtbar ist, macht der syntaktische Kontext Verwendungen eindeutig, die sich auf unterschiedliche Entitäten beziehen. Somit gibt es getrennte Namensräume für verschiedene Kategorien von Bezeichnern wie folgt:
— Labelnamen (disambiguiert durch die Syntax der Label-Deklaration und -Verwendung);
– das Stichworte von Strukturen, Vereinigungen und Aufzählungen (disambiguiert durch folgendes any32) der Schlüsselwörter struct
, union
oder enum
);
– das Mitglieder von Strukturen oder Gewerkschaften; Jede Struktur oder Union hat einen separaten Namensraum für ihre Mitglieder (disambiguiert durch den Typ des Ausdrucks, der für den Zugriff auf das Mitglied über die .
oder ->
Operator);
— alle anderen Bezeichner, sogenannte gewöhnliche Bezeichner (in gewöhnlichen Deklaratoren oder als Aufzählungskonstanten deklariert).
Das bedeutet, dass ein Objekt und ein Etikett können durch dieselbe Kennung bezeichnet werden. Um den Compiler an dieser Stelle wissen zu lassen, dass die Adresse von foo
ist die Adresse eines Etiketts, nicht die Adresse eines Objekts foo
(falls vorhanden), GCC definiert &&
Operator für die Adresse des Etiketts.
Ich denke, die eigentliche Frage ist: „Warum haben sie es nicht so definiert?
__address_of_label(label)
?”– Benutzer694733
28. April 2015 um 8:03 Uhr
Verwandt: gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
– PP
28. April 2015 um 11:11 Uhr