Was macht ## (Double Hash) in einer Präprozessordirektive?

Lesezeit: 4 Minuten

Benutzeravatar von DavidColson
David Colson

#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;

Die obige Zeile stammt aus Unreal 4, und ich weiß, dass ich sie in den Unreal-Foren stellen könnte, aber ich denke, dies ist eine allgemeine C++-Frage, die hier gestellt werden sollte.

Ich verstehe, dass die erste Zeile ein Makro definiert, aber ich kenne mich mit Präprozessor-Spielereien in C++ nicht aus und bin daher dort verloren. Die Logik sagt mir, dass der umgekehrte Schrägstrich bedeutet, dass die Deklaration in der nächsten Zeile fortgesetzt wird.

FThreadSafeStaticStat sieht ein bisschen wie eine Vorlage aus, aber da sind #s drin und eine Syntax, die ich noch nie zuvor in C++ gesehen habe

Kann mir jemand sagen was das bedeutet? Ich verstehe, dass Sie möglicherweise keinen Zugriff auf Unreal 4 haben, aber es ist nur die Syntax, die ich nicht verstehe.

  • Sie können über den Operator ## lesen auf cpreferenceunter anderem

    – Kubbi

    9. April 2014 um 22:23 Uhr


  • ## ist/könnte als Verkettungsoperator bezeichnet werden.

    – dyp

    9. April 2014 um 22:23 Uhr


  • Oh, das ist ziemlich cool! Es erklärt ziemlich viel, danke. Aber warum wird das Schlüsselwort struct verwendet? Die Zeile sieht eher aus wie eine Variablendefinition

    – DavidColson

    9. April 2014 um 22:27 Uhr


  • Das struct stellt ein aufwendiger Typbezeichner Soweit ich sagen kann.

    – dyp

    9. April 2014 um 22:34 Uhr


  • Der offizielle Name lautet „Token-Pasteing-Operator“, weil er zwei Vorverarbeitungstoken kombiniert, um einen anderen zu erzeugen. Beachten Sie, dass es nur gültig ist, wenn das Ergebnis ein gültiges Vorverarbeitungstoken ist, z. B. können Sie es nicht tun + ## 3 zu machen +3. (Aber man kann + 3 natürlich ohne Operator)

    – MM

    31. Januar 2017 um 9:04 Uhr


Benutzeravatar von Susam Pal
Susan Pal

## ist der Präprozessoroperator für die Verkettung.

Also, wenn Sie verwenden

DEFINE_STAT(foo)

irgendwo im Code wird es durch ersetzt

struct FThreadSafeStaticStat<FStat_foo> StatPtr_foo;

bevor Ihr Code kompiliert wird.

Hier ist ein weiteres Beispiel von ein Blogbeitrag von mir, dies näher zu erläutern.

#include <stdio.h>

#define decode(s,t,u,m,p,e,d) m ## s ## u ## t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
    printf("Stumped?\n");
}

Dieses Programm würde erfolgreich kompiliert und ausgeführt werden und die folgende Ausgabe erzeugen:

Stumped?

Wenn der Präprozessor für diesen Code aufgerufen wird,

  • begin wird durch ersetzt decode(a,n,i,m,a,t,e)
  • decode(a,n,i,m,a,t,e) wird durch ersetzt m ## a ## i ## n
  • m ## a ## i ## n wird durch ersetzt main

So effektiv, begin() wird durch ersetzt main().

  • Warum decode(a,n,i,m,a,t,e) wird durch ersetzt m ## a ## i ## n? Wie ist das??

    – Kaiyakha

    28. Juli um 9:25 Uhr

  • Das TL; DR, warum die Denksportaufgabe Stumped-> Animate-> funktioniert, ist, dass die Funktion “decode” so eingerichtet ist, dass sie die Eingabe “a”, “n”, “i”, “m” hat. Diese Eingänge werden dem zugeordnet Variablen „s“, „t“, „u“, „m“. Diese Variablen werden dann mit der Präprozessor-String-Concatenation-Direktive in die richtige Reihenfolge gebracht m ## s ## u ## t die die Eingabe “a”, “n”, “i”, “m” nimmt und die Zeichen neu anordnet, um das Wort “main” zu bilden, indem die Reihenfolge der geändert wird Variablen „s“, „t“, „u“, „m“. Ich fand es hilfreich, die Werte und die Variablen und die Zuordnungen zwischen ihnen zu zeichnen.

    – halsbrecherisch645

    28. September um 14:29 Uhr


Benutzeravatar von hmofrad
hmofrad

TLDR; ## ist für die Verkettung und # ist für die Stringifizierung (von cpReferenz).

Das ## verkettet aufeinanderfolgende Bezeichner und ist nützlich, wenn Sie eine Funktion als Parameter übergeben möchten. Hier ist ein Beispiel, wo foo akzeptiert ein Funktionsargument als erstes Argument und die Operatoren a und b als 2. und 3. Argument:

#include <stdio.h>
enum {my_sum=1, my_minus=2};
#define foo(which, a, b) which##x(a, b)
#define my_sumx(a, b) (a+b)
#define my_minusx(a, b) (a-b)

int main(int argc, char **argv) {
    int a = 2;
    int b = 3;
    printf("%d+%d=%d\n", a, b,  foo(my_sum, a, b));  // 2+3=5
    printf("%d-%d=%d\n", a, b, foo(my_minus, a, b)); // 2-3=-1
    return 0;
}

Das # verkettet den Parameter und schließt die Ausgabe in Anführungszeichen ein. Das Beispiel ist:

#include <stdio.h> 
#define bar(...) puts(#__VA_ARGS__)
int main(int argc, char **argv) {
    bar(1, "x", int); // 1, "x", int
    return 0;
}

1423040cookie-checkWas macht ## (Double Hash) in einer Präprozessordirektive?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy