Wie verwende ich __VA_ARGS__ in einer C-Funktion anstelle eines Makros? [duplicate]

Lesezeit: 4 Minuten

Benutzer-Avatar
Jona

Mögliches Duplikat:

C/C++: Variable Anzahl von Argumenten herumreichen

Ich verwende derzeit das folgende Makro, das in meiner C-Datei deklariert ist.

#define COMMON_Print(...) printf (__VA_ARGS__)

Jetzt funktioniert dieser Aufruf einwandfrei, aber es stellt sich heraus, dass ich in der Lage sein muss, eine C-Funktion zu erstellen, die ungefähr so ​​​​aussieht:

void COMMON_Print(...)
{    
    printf (__VA_ARGS__);
}

Diese Funktion funktioniert also nicht, ich erhalte eine Fehlermeldung

“Fehler: nicht definierte Kennung __VA_ARGS__”

Die Komplexität meines Projekts erfordert eine Funktion, da es sich um eine Schnittstelle handelt … Wie kann ich also die Parameter abrufen … und an die printf-Funktion übergeben? Oder besser was mache ich falsch?

Vielen Dank!

  • Siehe dazu stackoverflow.com/questions/205529/…

    – Kos

    2. Dezember 2010 um 20:19 Uhr

Benutzer-Avatar
John Kugelmann

Jedes von den ?printf Funktionen hat eine entsprechende v?printf Funktion, die dasselbe tut, aber a nimmt va_listeine variable Argumentliste.

#include <stdio.h>
#include <stdarg.h>

void COMMON_Print(char *format, ...)
{
    va_list args;

    va_start(args, format);
    vprintf(format, args);
    va_end(args);
}

Randnotiz: Beachte das va_start nimmt den Namen des letzten Arguments vor dem an ... als Parameter. va_start ist ein Makro, das einige Stack-basierte Magie anwendet, um die Variablenargumente abzurufen, und es benötigt die Adresse des letzten festen Arguments, um dies zu tun.

Als Folge davon muss es mindestens ein festes Argument geben, an das Sie es übergeben können va_start. Aus diesem Grund habe ich die hinzugefügt format argumentieren, anstatt beim Einfacheren zu bleiben COMMON_Print(...) Erklärung.

Sehen: http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

  • Wenn Sie Makros verwenden, brauchen Sie kein vorangestelltes arg. Betrachten Sie dieses Beispiel: #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) Dies ist offensichtlich aus Sicht der Nutzung sehr praktisch.

    – Techniker

    28. Juli 2015 um 11:39 Uhr


Benutzer-Avatar
Michael Mrozek

__VA_ARGS__ ist nur für Makros; variadische Funktionen sind ziemlich unterschiedlich. Sie müssen verwenden va_start, va_arg und va_end aus stdarg.h sie zu handhaben.

Zunächst benötigt Ihre Funktion mindestens einen benannten Parameter, z.

void COMMON_Print(const char* fmt, ...)

Dann können Sie a definieren va_list und verwenden va_start um es einzustellen:

va_list args;
va_start(args, fmt);
// your code here
va_end(args);

Jetzt können Sie verwenden args um auf die Argumente zuzugreifen; Berufung va_arg(args, TYPE) gibt das nächste variadische Argument zurück, also können Sie es einfach weiter aufrufen, bis Sie alle Argumente gelesen haben.

Wenn Sie nur versuchen anzurufen printfgibt es eine printf-Variante namens vprintf das nimmt die va_list direkt:

vprintf(fmt, args);

Es gibt keinen einfachen Weg, eine variadische Funktion von einer anderen aufzurufen; du brauchst sowas wie vprintf das nimmt das ganze va_list

  • Danke für Ihre Erklärung. Danke für die Hilfe und Erklärungen, die wirklich geholfen haben! 🙂

    – Jonas

    2. Dezember 2010 um 20:33 Uhr


  • ‘va_arg(args, TYPE)’ gibt NULL nur zurück, wenn NULL vom Aufrufer übergeben wurde. Es gibt keine Standard-Endbedingung für va_arg. Sie müssen entweder einen Sentinel-Wert übergeben oder die genaue Anzahl von Parametern kennen, die von einem Parameter übergeben werden, oder indem Sie die Anzahl von % in einer Zeichenfolge im printf-Format zählen.

    – Patrick Schlüter

    2. Dezember 2010 um 21:05 Uhr

  • @tristopia Oh, richtig; Ich habe die Angewohnheit, NULL am Ende zu übergeben, wenn es nötig ist. Fest

    – Michael Mrozek

    2. Dezember 2010 um 21:08 Uhr

Benutzer-Avatar
Nr

__VA_ARGS__ ist nur für Makros.

Das Verketten der variablen Anzahl von Argumenten mit einer anderen Funktion kann nicht direkt erfolgen. Stattdessen müssen Sie eine va_list übergeben, und die Funktion, die Sie aufrufen, muss eine va_list annehmen. Glücklicherweise gibt es eine Variante von printf, die dies tut, Ihre Funktion muss so geschrieben werden:

void COMMON_Print(char *format,...)
{    
  va_list args;
  va_start(args,format);
  vprintf(format,args);
  va_end(args);
}

  • Vielen Dank für Ihre Antwort! Es funktioniert tatsächlich! Aber es gibt einige Formatierungsprobleme, die ich auf meiner Seite lösen muss, glaube ich. FYI, ich arbeite an einem eingebetteten Gerät.

    – Jonas

    2. Dezember 2010 um 20:32 Uhr

  • Was ist vaprintf? Oder ist es nur ein Tippfehler?

    – Vincent Fourmond

    1. Dezember 2015 um 14:42 Uhr

  • Dieses Codebeispiel enthält zwei Fehler. Der erste Anruf sollte sein va_start und nicht va_begin und der zweite Aufruf an vprintf nicht vsprintf.

    – Björn Lindqvist

    19. Oktober 2021 um 10:32 Uhr

Benutzer-Avatar
Dima

Was Sie suchen, ist die Ellipse Operator.

1369870cookie-checkWie verwende ich __VA_ARGS__ in einer C-Funktion anstelle eines Makros? [duplicate]

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

Privacy policy