2016-07-07 11 views
2

ich ein Makro schreiben, müssen entkommen, die MontageWie ein # in einem Makro

#define create_me(name) \ 
    __asm\ 
    mov name,#0x1021\ 
    __endasm\ 

Die # aber Kompilieren ist nicht auf Inline muss. Ich habe versucht, es als Parameter übergeben, aber das funktioniert auch nicht. Es besagt ungültiges Präprozessor-Token. Ich kann versuchen, eine Inline-Funktion zu verwenden, aber ich kann den Registernamen nicht dynamisch erstellen. Das heißt, ich habe keinen Zugriff auf die Variable name. Hat jemand irgendwelche Vorschläge zur Verwendung der # Operation innerhalb eines Makros?

Ich habe mir Escaping a # symbol in a #define macro? angesehen, aber ich habe klar erklärt, warum ich das Makro hier brauche. Mein Anwendungsfall ist anders.

+0

Welcher Compiler? – Neil

+0

SDCC, denke ich. http://sdcc.sourceforge.net/ – ecatmur

+0

Ja. SDCC Version 3.5 – losang

Antwort

4

einen Umweg über ein anderes Makro sollte es tun:

#define HASH_LIT # 
#define HASH() HASH_LIT 

#define create_me(name) \ 
    __asm\ 
    mov name,HASH()0x1021\ 
    __endasm 
+0

Ich habe das nicht versucht. Lass mich sehen, ob es kompiliert – losang

+0

Nein, wird nicht funktionieren. –

+0

@losang Das war aus der Erinnerung, und ich hatte die Hälfte davon vergessen. Hier ist die Arbeitsversion. – Quentin

0

Präprozessor Befehle/Direktiven beginnen immer mit einem scharfen Zeichen (#), Sie können es nicht für Ihre eigenen Symbole verwenden.

Wenn Sie eine Variable erstellen namens whatever0x1021 die token concatenation## verwenden:

#include <stdio.h> 

#define create_me(name) name ## 0x121 

int main(void) 
{ 
    int create_me(a); /* int a0x121; */ 

    return 0; 
} 
+0

Die Idee ist nicht, die Variable zu erstellen, sondern laden Sie die Variable mit Inline-Assembly. – losang

2

Für SDCC, verwenden Sie die neue __asm__ Format.

#define create_me(name) \ 
     __asm__("mov " #name ", #0x1021") 
0

Es hilft, die Art des Problems zu verstehen. Das # Symbol ist das Besondere an dem Vorprozessor auf drei Arten:

  1. eine Source-Leitung, deren erste Vorverarbeitung Token ist # vom Präprozessor erkannt wird als nicht eine „Textzeile“ zu sein. Das heißt, es enthält Anweisungen für den Präprozessor. Textzeilen hingegen sind die zu verarbeitenden Daten - meist C-Programmquelle, möglicherweise aber mit zu erweiternden Makros. Das # ist in diesem Sinne nicht speziell, wenn es nicht das erste Vorverarbeitungstoken in der Zeile ist.

  2. Unter den Vorverarbeitungstoken der Ersetzungsliste für ein funktionsähnliches Makro ist das Token # der Stringifikationsoperator. Es dient jedoch nicht diesem Zweck in einem Variablen-ähnlichen Makro, noch wenn Makro-expandierter Text erneut für einen weiteren Makroersatz gescannt wird.

  3. Unter den Vorverarbeitungstoken der Ersetzungsliste für ein funktionsähnliches Makro ist das Token ## der Token-Pasting-Operator. Es dient jedoch nicht diesem Zweck in einem Variablen-ähnlichen Makro, noch wenn Makro-expandierter Text erneut für einen weiteren Makroersatz gescannt wird.

Sie können nicht die Bedeutung des # an den Präprozessor entkommen per se, aber Sie können trotzdem Ihre gewünschte Makro implementieren, indem ein Bit Indirektionsebene verwendet wird, wie @Quentin demonstriert. An erster Stelle, wenn ein # in der Erweiterung eines funktionsähnlichen Makros erscheinen soll, dann kann es nicht direkt im Ersetzungstext dieses Makros erscheinen, wo es als Stringifikationsoperator interpretiert würde. Es muss stattdessen eingeführt werden, indem ein anderes Makro erweitert wird. An zweiter Stelle, wenn es anderen Text ohne Zwischenraum dazwischen treffen muss, muss das unmittelbare Makro, das zu ihm expandiert, ein funktionsähnliches Makro selbst sein, so dass die Klammern dazu dienen, den Makronamen vom angrenzenden Text zu trennen. Das erfordert eine zweite Ebene der Indirektion.