Was bedeutet && in void * p = && abc;

102

Ich bin auf einen Code gestoßen void *p = &&abc;. Welche Bedeutung hat &&hier? Ich kenne rWert-Referenzen, aber ich denke &&, dass die Verwendung in diesem Zusammenhang anders ist. Was bedeutet &&in void *p = &&abc;?

Brent Arien
quelle
14
Wo hast du das gesehen?
user541686
3
Ich würde auch gerne wissen, wo Sie das gesehen haben.
Flavius

Antworten:

154

&&ist die Erweiterung von gcc , um die Adresse des in der aktuellen Funktion definierten Labels abzurufen.

void *p = &&abc ist in Standard C99 und C ++ illegal.

Dies wird mit g ++ kompiliert.

Prasoon Saurav
quelle
42
Stellen Sie sich nun vor, wie besser jeder Programmierer wäre, wenn gcc standardmäßig -pedantic hätte. Dann würden die Leute C lernen, anstatt irrelevante Informationen über Gnus.
Lundin
4
Was für ein Hack. Wenn sie eine neue Syntax für Beschriftungszeiger erfinden, sollten sie auch einen neuen Typ dafür erfinden, anstatt ihn zu verwenden void*.
Mark Ransom
1
@Prasoon Saurav: Wer auch immer herabgestimmt hat, missbilligt die Funktion wahrscheinlich und nimmt sie an Ihnen heraus.
Chuck
@Lundin: Gleiches gilt für die meisten Compiler. __forceinline? __declspec(naked)? Einer meiner Lieblings-MSVCisms ist : template<typename T> class X { friend T; }, der ungültige C ++ 03 ist.
Sebastian Mach
Der zweite Link ist tot.
Cœur
96

Wie man es herausfindet

Das ist die Adresse eines Etiketts und eine für GCC spezifische Funktion .

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

Sie hätten es selbst herausfinden können, indem Sie Folgendes getestet haben:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

In diesem Fall sagt GCC:

Fehler: Bezeichnung 'a' verwendet, aber nicht definiert

Unter der Haube - Montage

Sie müssen Assembler kennen, um dies wirklich zu verstehen, aber ich werde versuchen, Ihnen zu erklären, was eine Adresse eines Etiketts bedeutet.

Nachdem das Betriebssystem die EXE-Datei von der Festplatte geladen hat, eine Komponente des Betriebssystems namens "The Loader" (Windows hat den "PE Loader", Linux hat "ELF Loader" oder vielleicht sogar andere, wenn sie in der kompiliert sind Kernel), es macht eine "Virtualisierung" dieses Programms und verwandelt es in einen Prozess.

Dieser Prozess glaubt, dass es der einzige im RAM ist und Zugriff auf den gesamten RAM hat (dh 0x00000000-0xFFFFFFFF auf einem 32-Bit-Computer).

(Das Obige ist nur ein kurzer Überblick über das, was passiert. Sie müssen wirklich die Montage lernen, um es vollständig zu verstehen.

Das Label in einem Quellcode ist im Grunde eine Adresse. "gehe zu Etikett;" macht nichts anderes als einen Sprung zu dieser Adresse (denken Sie an den Befehlszeiger in der Assembly). Dieses Etikett speichert diese RAM-Adresse, und so können Sie diese Adresse herausfinden.

Nachdem Sie ASM gelernt haben, werden Sie feststellen, dass diese Adresse auf eine Anweisung im .textAbschnitt der ausführbaren Datei verweist . Der .textAbschnitt enthält den (Binär-) Code Ihres Programms, der ausgeführt werden soll.

Sie können dies überprüfen mit:

objdump -x a.out

Ein praktisches Beispiel

Wie in GCC beschrieben , können Sie damit eine Sprungtabelle initialisieren. Einige Scannergeneratoren wie re2c (siehe -gParameter) verwenden dies, um kompaktere Scanner zu generieren. Vielleicht gibt es sogar einen Parser-Generator, der dieselbe Technik verwendet.

Flavius
quelle
4
Kompilieren Sie mit -std = c99 -pedantic.
Lundin
2
Es ist ziemlich wichtig zu erwähnen, dass es sich um eine GCC-Erweiterung handelt und nicht um einen Kernbestandteil der Sprache
Jalf
1
Das ist ziemlich beeindruckend, Flavius.
Octavian A. Damiean
1
Ich mag diese Art von Antwort, mehr Menschen müssen lernen, wie man Antworten findet, anstatt nur erzählt zu werden.
Letseatlunch
1
Vielen Dank für die ausführliche Erklärung. Schätzte die Analyse im Zusammenhang mit der Versammlung.
CᴴᴀZ