Wie kann ich aus dem Wert eines C-Makros eine Zeichenfolge erstellen?

Lesezeit: 3 Minuten

Benutzeravatar von jfs
jfs

Wie kann ich beispielsweise vermeiden, dass „func_name“ zweimal geschrieben wird?

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME "func_name"
#endif

Ich möchte dem folgen Single Point of Truth Regel.

Version des C-Präprozessors:

cpp --version

Ausgang:

cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)

  • Mögliches Duplikat von C-Makros zum Erstellen von Zeichenfolgen

    – Richard Stelling

    6. Okt. 2015 um 10:34

Jonathan Lefflers Benutzeravatar
Jonathan Leffler

Der Schüchterne* 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 liegt in der Zeile „puts()“ – das Problem ist ein „verirrtes #“ in der Quelle.

In Abschnitt 6.10.3.2 des C-Standards „Der #-Operator“ heißt es:

Auf jedes # Vorverarbeitungstoken in der Ersetzungsliste für ein funktionsähnliches Makro muss ein Parameter als nächstes Vorverarbeitungstoken in der Ersetzungsliste folgen.

Das Problem besteht darin, dass Sie Makroargumente in Zeichenfolgen konvertieren können – Sie können jedoch keine zufälligen Elemente konvertieren, die keine Makroargumente sind.

Um den gewünschten Effekt zu erzielen, müssen Sie also mit Sicherheit etwas mehr 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 möchten und wie Sie Wiederholungen ganz vermeiden wollen. Dieses etwas ausführlichere Beispiel könnte informativer sein. Die Verwendung eines Makros, das STR_VALUE entspricht, ist eine Redewendung, die 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);
}

* Als diese Antwort zum ersten Mal geschrieben wurde, verwendete Shooshs Namen „Shy“ als Teil des Namens.

  • Fast wörtliche Neufassung eines Kommentars, der ursprünglich am 12.10.2012 um 21:37 Uhr verfasst wurde (in dem fett gedruckt war). Funktion anstatt __func__) – Natürlich könnten wir in C99 das verwenden __func__ Vordefinierter Bezeichner in der Funktion, der den Funktionsnamen bedeutet. Außerhalb der Funktion ist das jedoch keine Hilfe, und hier wird die Funktionsnamenzeichenfolge wirklich benötigt.

    – Jonathan Leffler

    29. Dezember 2013 um 18:17 Uhr

Benutzeravatar von jfs
jfs

Die Lösung von Jonathan Leffler 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

Ausgang:

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: Wikipedia C-Präprozessor Buchseite

1454430cookie-checkWie kann ich aus dem Wert eines C-Makros eine Zeichenfolge erstellen?

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

Privacy policy