Wie kann man zum Beispiel vermeiden, „func_name“ zweimal zu schreiben?
#ifndef TEST_FUN
# define TEST_FUN func_name
# define TEST_FUN_NAME "func_name"
#endif
Dem möchte ich folgen Einziger Punkt der Wahrheit Regel.
Version des C-Präprozessors:
$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Wer schüchtern ist* gab dir den Keim einer Antwort, aber nur den Keim. Die grundlegende Technik zum Konvertieren eines Werts in einen String im C-Präprozessor erfolgt zwar über den ‘#’-Operator, aber eine einfache Transliteration der vorgeschlagenen Lösung führt zu einem Kompilierungsfehler:
#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC
#include <stdio.h>
int main(void)
{
puts(TEST_FUNC_NAME);
return(0);
}
Der Syntaxfehler befindet sich in der ‘puts()’-Zeile – das Problem ist ein ‘verirrtes #’ in der Quelle.
In Abschnitt 6.10.3.2 des C-Standards „Der #-Operator“ heißt es:
Jedem # Vorverarbeitungstoken in der Ersetzungsliste für ein funktionsähnliches Makro soll ein Parameter als nächstes Vorverarbeitungstoken in der Ersetzungsliste folgen.
Das Problem ist, dass Sie Makroargumente in Zeichenfolgen konvertieren können – aber Sie können keine zufälligen Elemente konvertieren, die keine Makroargumente sind.
Um den gewünschten Effekt zu erzielen, müssen Sie also mit Sicherheit etwas zusätzliche Arbeit leisten.
#define FUNCTION_NAME(name) #name
#define TEST_FUNC_NAME FUNCTION_NAME(test_func)
#include <stdio.h>
int main(void)
{
puts(TEST_FUNC_NAME);
return(0);
}
Mir ist nicht ganz klar, wie Sie die Makros verwenden und wie Sie Wiederholungen insgesamt vermeiden möchten. Dieses etwas ausführlichere Beispiel könnte informativer sein. Die Verwendung eines Makros, das STR_VALUE entspricht, ist ein Idiom, das erforderlich ist, um das gewünschte Ergebnis zu erzielen.
#define STR_VALUE(arg) #arg
#define FUNCTION_NAME(name) STR_VALUE(name)
#define TEST_FUNC test_func
#define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC)
#include <stdio.h>
static void TEST_FUNC(void)
{
printf("In function %s\n", TEST_FUNC_NAME);
}
int main(void)
{
puts(TEST_FUNC_NAME);
TEST_FUNC();
return(0);
}
* Zu der Zeit, als diese Antwort zum ersten Mal geschrieben wurde, verwendete Shooshs Namen „Shy“ als Teil des Namens.
@Jonathan Leffler: Danke. Deine Lösung funktioniert.
Ein vollständiges Arbeitsbeispiel:
/** compile-time dispatch
$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
*/
#include <stdio.h>
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#ifndef TEST_FUN
# define TEST_FUN some_func
#endif
#define TEST_FUN_NAME STR(TEST_FUN)
void some_func(void)
{
printf("some_func() called\n");
}
void another_func(void)
{
printf("do something else\n");
}
int main(void)
{
TEST_FUN();
printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME);
return 0;
}
Beispiel:
$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
do something else
TEST_FUN_NAME=another_func
#include <stdio.h>
#define QUOTEME(x) #x
#ifndef TEST_FUN
# define TEST_FUN func_name
# define TEST_FUN_NAME QUOTEME(TEST_FUN)
#endif
int main(void)
{
puts(TEST_FUN_NAME);
return 0;
}
Referenz: Wikipedias C-Präprozessor Seite
#define TEST_FUN_NAME #FUNC_NAME
sehen hier
Mögliches Duplikat von C-Makros zum Erstellen von Zeichenfolgen
– Richard Stelling
6. Oktober 2015 um 10:34 Uhr