mikrocontroller.net

Forum: Compiler & IDEs Übergabe unbekannter Parameteranzahl


Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich weiss nicht warum, aber heute habe ich mich gefragt, wie macht man 
eigentlich eine unbestimmte Parameterübergabe (Anzahl der Parameter und 
Typ) ähnlich wie bei bei printf? D.h. wie kann ich folgendes 
realisieren:

Aufrufmöglichkeit 1:
 int Dezimalzahl = 10;
 float Floatzahl = 1.0;
 Unterprogramm("Dezimalzahl = %d, Floatzahl = %f", Dezimalzahl, 
Floatzahl);

Aufrufmöglichkeit 2:
 uint8 Bytezahl = 'h';
 Unterprogramm("Bytezahl = %c", Bytezahl);

In dem Fall weiss ich bei der Programmierung des Unterprogrammes(...) 
vorher nicht genau, wieviele Parameter vorhanden sind, und von welchem 
Typ sie sind.

Bei den ganzen Einführungen in C bin ich nicht in endlicher Zeit auf 
eine Lösung gestoßen. Ein eigenes C Buch möchte ich mangels konkretem 
Ziel nicht beschaffen.

Im Forum gab es sicherlich schon mal eine Lösung zu dieser Frage, eine 
Lösung konnte ich aber nicht finden.

Vielen Dank.
Heiko.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dazu gibt es Unterstützungsfunktionen in varargs.h
/* Returns the average of a variable list of integers. */
int average(int first, ...)
{
  int count = 0, sum = 0, i = first;
  va_list marker;

  va_start(marker, first);     /* Initialize variable arguments. */
  while (i != -1)
  {
    sum += i;
    count++;
    i = va_arg(marker, int);
  }
  va_end(marker);              /* Reset variable arguments.      */
  return(sum ? (sum / count) : 0);
}

// Aufruf, letztes Argument wird durch -1 gekennzeichnet

average(2, 3, 4, -1);

Ein Problem hierbei ist, daß die Anzahl der übergebenen Argumente nicht 
bestimmbar ist. Also muss entweder als eigener Parameter deren Anzahl, 
etwas woraus deren Anzahl bestimmt werden kann oder wie im Beispiel eine 
eindeutige Ende-Kennung als letzter Parameter übergeben werden.

"Etwas woraus deren Anzahl bestimmt werden kann" ist beispielsweise der 
Formatstring, der printf/scanf übergeben wird.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Info,

dann werde ich demnächst mal damit spielen. Vielleicht braucht man sowas 
ja mal kurzfristig in einem Bastel-Projekt.

Gruß,

Heiko.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für printf() wäre noch anzumerken, dass es eine Form gibt (vprintf()
& Co.), bei denen das va_arg direkt weitergereicht werden kann.
Damit kann die Parameterliste unbestimmter Länge weitergeleitet
werden, ohne dass man genau wissen muss, welche und wie viele
Parameter es genau waren.
#include <avr/io.h>

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

void
myprint(uint8_t leds, const char *fmt, ...)
{
        va_list ap;

        PORTB = leds;

        va_start(ap, fmt);
        (void)vprintf(fmt, ap);
        va_end(ap);
}

(Ja, bitte <stdarg.h> benutzen, nicht <varargs.h>.  Das ist ein alter
Name.)

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Vielleicht braucht man sowas ja mal kurzfristig in einem
> Bastel-Projekt.

Eher nicht.
Um sowas sollte man einen grossen Bogen machen.
Wenn irgendwie möglich lieber nach einer Alternative
suchen. Die gibt es. Zb. dadurch dass alle Argumente,
so sie denn vom gleichen Typ sind, in ein einfaches
Array gesteckt werden. Array + Größe des Arrays an
die Funktion übergeben, fertig.

Die Anzahl der Fehler die enstanden sind, weil bei
printf bzw. scanf die tatsächlichen Argument nicht mit
den Angaben im Format-String übereinstimmten, sind Legion.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Um sowas sollte man einen grossen Bogen machen.

Es gibt noch einen zweiten Grund, warum man das vermeiden will:
die Parameter der variablen Liste werden immer über den Stack
übergeben.  Normalerweise kann der AVR-GCC aber bis zu 18 Bytes
an Parametern in Registern übergeben.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.