Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » ... in funktions deklaration?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
10.10.2003, 01:23 Uhr
BeS



Hallo,
ich habe in manchem C code Funktionen gesehen, die so deklariert sind:


C++:
int request_module(const char *fmt, ...)
{
..
}



was bedeutet das ... in der Funktionsdeklaration? Was kann ich der Funktion noch übergeben, außer einem string?

Danke!
--
If art interprets our dreams, the computer execute them in the guise of programs!

Dieser Post wurde am 10.10.2003 um 01:23 Uhr von BeS editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
10.10.2003, 07:59 Uhr
Pablo
Supertux
(Operator)


Solche Funktionen heißen Ellipsen. Die meisten Programmierspachen legen ihre Argument von "links nach Rechts" auf den Stack auf, C tut das nach de ANSI standarisierung. Aber der Unterschied zwischen C und die meisten Sprachen wie PASCAL ist, dass C Funktionen mit Variable (unbekannte meine ich damit) Länge an Parametern unterstützt, und das sind eben Ellipsen.

Früher hat C immer die Argumnte von rehts nach links gelegt, damit Ellipsen geben kann. Das aber in vielen Fällen ein Nachteil war. Deshalb hat das ANSI-Komite das geändert und nur Argumente von Ellipsen werden von rechts nach links auf den Stack gelegt.

C hat eine Standard Header Datei, stdarg.h, die va_list Zeiger und spezielle Makros definiert um die Abfrage der Argumente zu ermöglichen.

Um eine variable Anzahl von Argumenten innrhalb einer Ellipse abarbeiten zu können, sind folgende Schritte notwendig: (der Zugriff auf die Feste Parameter ändert sich nicht.)

1. Deklaration einen Variablenzeiger des Typs va_list, so

C++:
va_list arg_list_zgr;


2. Aufruf des Makros va_start mit 2 Argumenten: Dem Namen des deklarierten zeigers und des letzten fixen Parameter

C++:
va_start(arg_list_zgr, letzt_param);

http://www.fun-soft.de/showtopic.php?threadid=3745
Ohne diesen Aufruf ist das ganze nicht möglich
3. va_arg gibt den Wert der verschiedene Parameter durch wiederholten Aufruf des Makros, das ertse Argument ist arg_list_zgr und das zweite der Name des Datentyp, zb int.

C++:
va_arg(arg_list_zgr, [i]datentyp[/i]);



Guck mal hier, dieses Rätsel habe ich mit einer Ellipse gelöst:
www.fun-soft.de/showtopic.php?threadid=3745

Hier habe ich immer va_arg(az, int), weil ich wusste, dass ich nur ints übergeben würde.

[color="red"]
Bearbeitung:
Achtung:[/color] Ich wusste, dass ich etwas vergessen habe, und zwar ganz wichtig. Du musst immer das Makro va_end aufrufen, bevor die Funktion verlassen wird, damit arg_list_zgr auf NULL gesetzt wird und den Stack geräumt, sonst kannst du böse Überrraschungen erleben. Das einzige Argument von va_end ist den Zeiger.

C++:
va_end(arg_list_zgr);




--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 10.10.2003 um 08:28 Uhr von Pablo Yanez Trujillo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
10.10.2003, 08:28 Uhr
virtual
Sexiest Bit alive
(Operator)


Jau, hier nochmal ein etwas komplexeres Beispiel: ein eigenes printf, das %s und %d versteht:

C++:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void poor_mans_printf(const char* format, ... )
{
    va_list args; /* Mit dieser Variablen kann man auf die ... zugreifen, siehe unten */
    const char* s = format; /* Irgendeine Variable eben, */
    const char* e; /* Noch eine */
    char* strvar;
    int intvar;

    /* Initialisiere args. Mit args kann man später von ersten zum letzten
       Argument, welches durch ... übergeben wurde, wandern. Dafür muß man
       allerdings wissen, wo das ... anfängt, deshalb übergibt man bei der
       initialisierung den Namen des letzten arguments vor dem ... */

    va_start(args, format);

    while (NULL != (e=strchr(s, '%'))) /* Solange % gefunden wird... */
    {
        /* Schreibe den Text bis vor dem % Zeichen */
        while (s<e) putchar(*s++);

        /* Überspringe das % Zeichen(uns interessiert das zeichen danach */
        s++;
        if (*s == 0)
        {
            /* Oje, string einfach zuende */
            s = NULL;
            break;
        }

        /* Nun je nach formatstring weiter */
        switch (*s++)
        {
        case '%':
            putchar('%');
            break;
        case 's':
            /* Das nächste Argument ist eine String; wird benutzen va_arg,
               um das nächste Argument zu kommen; dabei müssen wir aber sagen,
               welchen Datentyp wir erwarten */

            strvar = va_arg(args, char*);
            while (*strvar) putchar(*strvar++);
            break;
        case 'd':
            /* Hier liegt ein int vor; auchbenutzen wir va_arg,
               um das nächste Argument zu kommen; dabei müssen wir aber sagen,
               welchen Datentyp wir erwarten */

            intvar = va_arg(args, int);
            if (intvar<0) putchar('-');
            if (intvar!=0)
            {
                char buffer[12];
                int i = 0;
                while (intvar!=0)
                {
                    buffer[i] = intvar%10;
                    if (buffer[i]<0) buffer[i] = -buffer[i];
                    intvar /= 10;
                    i++;
                }
                while (--i>=0)
                {
                    putchar('0'+buffer[i]);
                }
            }else
            {
                putchar('0');
            }
            break;
        }
    }

    /* Gebe den ende des Strings aus */
    if (s) while(*s) putchar(*s++);

    /* Am ende sollte immer va_end aufgerufen werden, um den Speicher freizugeben */
    va_end(args);
}


int main()
{
    poor_mans_printf("%s ist %d", "hundert", 100);
}


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 10.10.2003 um 08:28 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
10.10.2003, 08:43 Uhr
Pablo
Supertux
(Operator)


Dieses Beispiel finde ich auch sehr schön, das ist im Buch Linux·Unix Programmierung von Helmut Herold, sehr schönes Buch


C++:
#include <stdio.h>
#include <stdarg.h>

void myprintf(const char *fmt, ...)
{
    va_list az;
    char puffer[4096];
    
    va_start(az, fmt);
    while(*fmt) {
      if (*fmt != '%')
          putc(*fmt, stdout);
       else {
            switch(*++fmt) {
                case 'c' : putc(va_arg(az, int), stdout); break;
                case 'd': printf("%d", va_arg(az, int)); break;
                case 'f' : printf("%f", va_arg(az, double)); break;
                case 's' : printf("%s", va_arg(az, char *)); break;
                case 'l' : if (*++fmt=='d')
                                        printf("%ld", va_arg(az, long));
                              else
                                        printf("%lf", va_arg(az, double));
                               break;
            }
       }
        fmt++;
    }
    printf("\n");
    va_end(az);
}

int main()
{
    myprintf("%d %d %d Hello %s", 2, 3, 2*3, "World");
}



Ich hab einige kleine Änderungen gemacht
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 10.10.2003 um 08:43 Uhr von Pablo Yanez Trujillo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
10.10.2003, 17:46 Uhr
BeS



Hallo,
Danke euch beiden!

Eine Frage dazu hätte ich aber noch:
Warum werden die festen Argumente, in den Beispielen hier immer char*, als const deklariert? Bei meinen bisherigen Tests hast es keinen Unterschied gemacht ob mit oder ohne const.

Danke!
--
If art interprets our dreams, the computer execute them in the guise of programs!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
10.10.2003, 19:08 Uhr
~(un)wissender
Gast


const char * var, sagt aus, dass ich den Pointerwert, also den Zeiger selber, nicht verändert haben möchte.
C++ unterstützt den Programmierer mit const dabei.
Was sich hinter var verbirgt, kann sehr wohl verändern werden.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
11.10.2003, 00:31 Uhr
Pablo
Supertux
(Operator)


Nein. ein const char* ist ein Zeiger auf eine Konstante. Du kannst den Zeiger auf eine andere Adresse zeigen lassen, aber du darfs die Variable auf die er zeigt nicht verändern.

Warum wir das tun?
Es gibt 2 gute Gründe:
1. Wir wollen den Anwender der Funktion sagen, diese übergebene Zeichenkette wird von uns nicht verändert, sie ist nur read-only.
2. Das Problem mit den Ellipsen ist, dass du niemals weißt, wieviele und welche (ich meine vom Typ her) Argumente übergeben wurden. Du kannst ein anderes Argument haben, welches sagt, wieviele. Ein Beispeil davon ist das Rätsel von @virtual. Aber wenn du sowas nicht hast, dann weißt du auch nicht, welche und wie viele Argumente es gibt. Also muss man ein Format haben, und das ist eben const char* fmt. Was kann ein Format besser speichern als eine Zeichenkette? Mit Hilfe des Formates können wir wissen, was wir erwarten und wie viele Argumente es gibt. Deshlab nimmt man Ellipsen in der Regel für printf-like Funktionen. Ich habe allerdings Ellipsen nur in diesem Zusammenhang geshen.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
11.10.2003, 01:07 Uhr
~(un)wissender
Gast


Ups, habe ich verwechselt!
const char * var ist natürlich ein variabler Zeiger mit konstanten Daten, sorry.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: