2015-01-08 9 views
11

Say in einem Header, die ich selbst nicht lesen will, aber was ich bin, ich habeWie erhält man die Definition eines Makros als String-Literal?

#define A B 
#define B C 

Jetzt

#define STR(name) # name 

definiert einen Makro, das mir den Namen eines Makros gibt als eine Zeichenfolge und

definiert ein Makro, das mir die vollständige Erweiterung eines Makros als Zeichenfolge gibt. So

cout << STR(A) << EXP_STR(A) << endl; 

wird AC drucken.

Gibt es eine Möglichkeit, "B" von A mithilfe einiger Makros zu erhalten?

+2

Ich bin mir nicht sicher. Ich glaube, das ist nicht möglich, weil die Token-Erweiterung in C funktioniert. Das ist eine sehr gute Frage. – fuz

+0

Es ist eine ausgezeichnete Frage, aber ich bin mir fast sicher, dass dies nicht möglich ist, hoffe jemand weiß, ob es ist, und wenn nicht, dann eine gute Erklärung. –

+2

mögliches Duplikat von [Vermeidung einer doppelten Makrosubstitution im C-Preprozessor] (http://stackoverflow.com/questions/27533994/avoiding-a-double-mac-substitution-in-the-c-pre-processor) – this

Antwort

1

Da Sie

#define B C 
#define A B 

#define STR(name) # name 
#define EXP_STR(name) STR(name) 

und die

cout << STR(A) << EXP_STR(A) << endl; 

ausgeben wird exaclty das gleiche schreiben, bedeutet das, dass es nicht möglich ist.

Wenn Sie das tun

#define A B 

und dann

#define B C 

jetzt bedeutet dies, dass A durch C und nicht B ersetzt werden, so wird es keine Möglichkeit, es zu tun, weil, wenn die cout Zeile ist der Preprozessor erreicht hat bereits A durch C ersetzt.

So die kurze Antwort ist, es nicht möglich ist weil der Präprozessor A würde mit C ersetzt haben, bevor die Datei kompiliert wird.

+0

Beachten Sie, dass die Zeile '#define AB' ** nicht definiert, dass A zu C gehört, nur weil B als C definiert ist. Wenn ich' #undef B', '#define BX' und dann' cout << STR (A) << << << EXP_STR (A) << endl; ', die Ausgabe wird AX sein. Die Erweiterung wird ausgeführt, wenn das Makro nicht aufgerufen wird, wenn es definiert ist. Einige Sprachen ([make] (https://www.gnu.org/software/make/manual/html_node/Flavors.html)) können für sich selbst nicht entscheiden, auf welche Weise sie es tun sollen. –

+0

@ not-a-user Ich habe meine Antwort geschrieben, bevor ich deinen Kommentar gesehen habe, aber ich biete eine gute Möglichkeit, dies zu tun ... –

0

Ja, es ist möglich. Sie müssen nur ein paar Cheats verwenden.

  • #undef B vor #define EXP_STR
  • Verwenden Sie ein paar mehr Dereferenzierungsebenen

Zum Beispiel:

#define A B 
#define B C 

#define _TEMP_VAR B // so that it can be redefined later 
#undef B    // so that EXP_STR(A) will return "B" 

#define EXP_STR__(x) (x) 
#define EXP_STR_(x) EXP_STR__(#x) 
#define EXP_STR(x) EXP_STR_(x) 

#define STR(x) # x 

#define B _TEMP_VAR // now you can still access A normally, defined to B (defined to C) 

Ein Testprogramm, es zu beweisen:

#include <stdio.h> 

int main(void) 
{ 
    printf("EXP_STR(A) = %s\n", EXP_STR(A)); 
    printf("STR(A)  = %s\n", STR(A)); 
} 

Ausgabe:

EXP_STR(A) = B 
STR(A)  = A 
+0

Könntest du das ein wenig klären? Müssen wir diesen ganzen Code für jedes Makro, das wir drucken wollen, machen? Oder nur einmal? – Vality

+0

@Vality Definieren Sie Makros, die Sie 'EXP_STR' vor dem' #define_TEMP_VAR' verwenden möchten. –

+0

Danke, upvoted. – Vality

Verwandte Themen