2012-04-02 10 views
4

Angenommen, es gibt eine Debug-Funktion, vereinfacht hier arbeitet als:Passing Variablennamen als Zeichenfolge mit Standardparametern

void DumpString(char* var, char* varname) { 
    printf("%s : '%s'\n", varname, var); 
} 

char str[10]="foobar"; 
DumpString(str, "str"); 

> str : foobar 

wir machen es einfacher, durch Entfernen der unnötigen Fremd Anforderung einer Übertragung der Variable zweimal, einmal in Zitate:

#define VARASSTR(v) #v 

void DumpString(char* var) { 
    printf("%s : '%s'\n", VARASSTR(var), var); 
} 

char str[10]="foobar"; 
DumpString(str); 

> var : foobar 

Hoppla! Es nutzt die lokale Variablennamen statt den übergebenen Lassen Sie uns versuchen, eine andere (und weniger ideal) tack.

#define DumpStr(v) DumpString(v, #v) 

void DumpString(char* var, char* varname) { 
    printf("%s : '%s'\n", varname, var); 
} 

char str[10]="foobar"; 
DumpStr(str); 

> str : foobar 

Groß es funktioniert. Was aber, wenn die Funktion ein wenig komplizierter war:

void DumpString(char* var, char* varname, int optionalvar=0) { 
    printf("%s : '%s'\n", varname, var); 
    printf("blah: %d", optionalvar); 
} 

Es ist nicht möglich, ein Makro zu überlasten, so wird DumpStr nicht funktioniert, und wir haben bereits die Version mit VARASSTR ausgeschlossen.

Wie kann das gehandhabt werden (ohne auf mehrere ähnliche, aber anders benannte Funktionen/Makros zurückgreifen zu müssen)?

+0

"Wie kann das gehandhabt werden (ohne auf mehrere ähnliche, aber anders benannte Funktionen/Makros zurückgreifen zu müssen)?" Es kann nicht. Sie können Makros nicht überladen. – meagar

+0

Sie sollten eine Sprache mit Reflexionsfunktionen ausprobieren. Nicht wirklich. – iehrlich

+1

Sie könnten [Variadic Makrotrick] (http: // stackoverflow.com/questions/5365440/variadic-macro-trick), um das Überladen mit Makros zu "simulieren". –

Antwort

1

Das ist Nicht-Standard, sondern arbeitet als eine Erweiterung in GNU C:

#define DumpStr(v, ...) DumpString(v, #v, ##__VA_ARGS__) 

In GNU C, keine Argumente zu einem variadische Makro übergeben kann, und der "token einfügen Operator" ## bei der Anwendung zwischen einem Komma und einer leeren variadischen Argumentliste erzeugt nichts (das nachfolgende Komma wird also unterdrückt). In Visual C++ glaube ich, dass der Token-Pasting-Operator ## unnötig ist (und das Makro wahrscheinlich zerbrechen wird), da Visual C++ automatisch ein abschließendes Komma unterdrückt, wenn es vor einer leeren variadischen Argumentliste angezeigt wird.

Beachten Sie, dass das einzige, was diesen Nichtstandard macht, der Wunsch ist, manchmal eine leere Argumentliste zu übergeben. Variadische Makros sind sowohl in C99 als auch in C++ 11 standardisiert.


Edit: Und hier ist ein Beispiel, das nicht Nicht-Standard-Funktionen nicht verwendet. Sie können sehen, warum wirklich einige Leute, wirklich so etwas wollen in der Norm behandelt:

#define DUMPSTR_1(v) DumpString(v, #v) 
#define DUMPSTR_2(v, opt) DumpString(v, #v, opt) 
#define DUMPSTR_NARG(...) DUMPSTR_ARG_N(__VA_ARGS__, 4, 3, 2, 1, 0) 
#define DUMPSTR_ARG_N(_1, _2, _3, _4, n, ...) n 
#define DUMPSTR_NC(f, ...) f(__VA_ARGS__) 
#define DUMPSTR_NB(nargs, ...) DUMPSTR_NC(DUMPSTR_ ## nargs, __VA_ARGS__) 
#define DUMPSTR_NA(nargs, ...) DUMPSTR_NB(nargs, __VA_ARGS__) 
#define DumpStr(...) DUMPSTR_NA(DUMPSTR_NARG(__VA_ARGS__), __VA_ARGS__) 

Es gibt wahrscheinlich ein paar sauberere Wege, dies zu tun. Aber nicht so viele.


Edit 2: Und hier ist noch ein weiteres Beispiel, das nicht Nicht-Standard-Funktionen nicht verwendet, mit freundlicher Genehmigung von R..

#define STRINGIFY_IMPL(s) #s 
#define STRINGIFY(s) STRINGIFY_IMPL(s) 
#define ARG1_IMPL(a, ...) a 
#define ARG1(...) ARG1_IMPL(__VA_ARGS__, 0) 
#define DumpStr(...) DumpString(STRINGIFY(ARG1(__VA_ARGS__)), __VA_ARGS__) 

Beachten Sie, dass dies das Argument Reihenfolge der DumpString erfordert geändert werden damit der Name der stringifizierten Funktion das erste Argument ist.

+0

Es gibt Lösungen für dieses Problem ohne nicht standardmäßige Hacks wie diese. –

+1

Insbesondere subsumieren Sie die gesamte Argumentliste in das '...' und verwenden dann Makros, die das erste Argument (oder den gewünschten Index) aus '__VA_ARGS__' extrahieren. –

+0

@R .. Ja, da ist. Und * wow * ist es erschreckend. Ich fügte eine in sich geschlossene Art hinzu, die ich trommelte. Können Sie einen besseren vorschlagen? –