Übergabe einer variablen Zahl von Argumenten



  • Ging das bei dir?

    Bei mir nicht, vielleicht habe ich aber auch etwas falsch gemacht. Jedenfalls ist execl immer fehlgeschlagen, wenn das Argument Whitespaces enthielt.

    Davon abgesehen funktioniert das leider nur im besonderen Fall der Charpointer. Wenn die jeweilige Funktion aber eine variable Anzahl von Integern by Value erwartet, wie geht's dann? Das ist jetzt wirklich nur noch ein Gedankenspiel und es würde mich auch wundern, aber es interessiert mich halt 😉

    Gruß, Volker



  • V0lle schrieb:

    Ging das bei dir?

    ja, funktioniert. allerdings unter windows. möglicher weise geht das unter linux nicht.

    V0lle schrieb:

    Wenn die jeweilige Funktion aber eine variable Anzahl von Integern by Value erwartet, wie geht's dann? Das ist jetzt wirklich nur noch ein Gedankenspiel und es würde mich auch wundern, aber es interessiert mich halt 😉

    man kann ja auch integerwerte in eine zeichenkette einpacken und wieder rauspulen.
    gruß,
    e.p.



  • Bööööses Linux, böse böse! 😉

    Man kann Integer in ne Zeichenkette packen, aber man kann ja die Zeichenkette nicht übergeben, weil in meinem Beispiel ja eine kommaseparierte Liste von Integern als Argument erwartet wird und kein Pointer auf den Anfang der Zeichenkette.

    Oder versteh ich schooon wieder etwas falsch? Also mein Prototyp ist jetzt beispielsweise:

    int berechne_Durchschnitt(int a1, ...);

    Diese Funktion soll beispielsweise den Durchschnitt der übergebenen positiven Integer-Werte ermitteln und erkennt das letzte Argument daran, dass es negativ ist.

    Jetzt könnte ich aufrufen "berechne_Durchschnitt(1,3,14,-1)" oder "berechne_Durchschnitt(17,1,235,1,66,2,2,26,2,26,3462,262,-1)".

    Wenn ich aber jetzt n dynamisches Integer-Array mit "int Zahlen[]" deklariere und das letzte Element mit -1 kenntlich mache, kann ich es ja trotzdem nicht übergeben, denn es werden ja Integer erwartet.

    "berechne_Durchschnitt(Zahlen)" geht dann also nicht, weil Zahlen ein Pointer ist und kein Integer. Eventuell steh ich etwas auf dem Schlauch, aber wenn du das mit der Zeichenkette anders gemeint hast, dann setz das doch vllt in meinem Beispiel um, wenn du magst, damit es auch für mich Trottel klar wird 😉

    Gruß, Volker



  • hi !
    ich habe nicht alles gelesen, was du geschrieben hast.
    aber für eine variable liste von parametern kannst du ach
    int execv(const char *path, char *const argv[]);
    benutzen
    🙂

    brauchst du das für einen bestimmten zweck oder ist es nur so, prizipielles interesse ?
    gruß
    d.v.



  • Danke für die Antwort, genau DAS habe ich soeben auch herausgefunden 😉

    Das ist nur prinzipielles Interesse, welches sich beim Benutzen dieser Funktion einfach ergeben hat. Die Frage, ob sowas prinzipiell auch irgendwie mit "execl()" oder meiner Beispielfunktion "berechne_Durchschnitt()" möglich wäre, bleibt daher trotzdem offen. 🙂 Meine Vermutung ist wie gesagt ohnehin, dass es nicht geht. 😉

    Gruß, Volker



  • Übrigens: Da mir eure sachlichen und relativ zügigen Antworten gefallen, habe ich mich entschlossen, euch auch in Zukunft unter Umständen häufiger zu nerven, falls sich Fragen ergeben. Und daher habe ich mich ma eben registriert.

    Gruß, Volker



  • übrigens: für dein Beispiel braucht man keine variable Parameterlist -.-

    #include <stdio.h>
    #include <malloc.h>
    
    int durchschnitt(int* pZahlen, int iAnzahl)
    {
        int Summe = 0, n;
        for (n = 0; n < iAnzahl; n++)
            Summe += pZahlen[n];
        return (Summe / iAnzahl);
    }
    
    int main(int argc, char** argv)
    {
        int iAnzahl, iDurchschnitt, n;
        int* pZahlen;
        printf("Wie viele Zahlen? ");
        scanf("%d", &iAnzahl);
        pZahlen = (int*)malloc(iAnzahl * sizeof(int));
        for (n = 0; n < iAnzahl; n++)
        {
            printf("> ");
            scanf("%d", &(pZahlen[n]));
        }
        iDurchschnitt = durchschnitt(pZahlen, iAnzahl);
        printf("Der Durchschnitt: %d\n", iDurchschnitt);
        free((void*)pZahlen);
        getchar();
        return 0;
    }
    


  • Hya ! 🕶

    V0lle85 schrieb:

    Übrigens: Da mir eure sachlichen und relativ zügigen Antworten gefallen, habe ich mich entschlossen, euch auch in Zukunft unter Umständen häufiger zu nerven, falls sich Fragen ergeben. Und daher habe ich mich ma eben registriert.

    Gruß, Volker

    Willkommen im Forum !



  • Hi!

    Proggingmania: Danke dir! 🙂

    DrakoXP: Auch dir danke ich für deine Antwort. Ich weiß, dass man mein Beispiel auch mit Übergabe by Reference realisieren kann. In meinem ersten Post schrieb ich auch, dass ich das weiß, dass mich die Frage jedoch einfach prinzipiell interessiert, ob das irgendwie funktionieren würde, falls mir mal eine höchstkomplizierte, schon vordefinierte Funktion begegnet, die mit variablen Argumentenlisten arbeitet und nicht mit Pointern, und die ich nicht selbst nochmal implementieren möchte.

    Könnte man in irgendeiner Weise den Argumentenstack manuell aufbauen und direkt übergeben, würde dies das natürlich ermöglichen, gleichzeitig aber natürlich sämtliche Überprüfungen durch den Compiler umgehen. Daher beantworte ich mir diese Frage jetzt einfach mit 'Nein'.

    Danke nochmal!

    Gruß, Volker



  • also im Normalfall muss feststehen, wie viele Parameter du der Funktion gibst!
    und das zur Compile-Time.

    das einige, was mir einfällt, wie das gänge,
    ist per Assembler:

    du pushst nacheinander die Parameter auf den Stack, callst dann deine Funtkion,
    die eine variable Parameterliste erwartet, und am Schluss machst du den Stack wieder sauber.



  • also, ich hab das jetzt mal ausprobiert mit inline-asm.
    das ganze läuft mit Visual C++, bei anderen Compilern sieht der inline-asm-Teil wahrscheinlich etwas anders aus.

    naja, hier is der Code:

    #include <stdio.h>
    #include <stdarg.h>
    #include <malloc.h>
    
    int __cdecl durchschnitt(int iAnzahl, ...)
    {
        unsigned int Summe = 0, n = 0;
        va_list pArgList;
        va_start(pArgList, iAnzahl);
        while (n < iAnzahl)
        {
            Summe += va_arg(pArgList, unsigned int);
            n++;
        }
        return (Summe / iAnzahl);
    }
    
    int main(int argc, char** argv)
    {
        unsigned int iAnzahl, iDurchschnitt, n, Extra, Buf;
        unsigned int* pZahlen;
        printf("Wie viele Zahlen? ");
        scanf("%d", &iAnzahl);
        pZahlen = (unsigned int*)malloc(iAnzahl * sizeof(unsigned int));
        for (n = 0; n < iAnzahl; n++)
        {
            printf("> ");
            scanf("%d", &(pZahlen[n]));
        }
        if (iAnzahl > 0)
        {
            __asm
            {
                push ecx;
                push eax;
                mov ecx, iAnzahl;
    push_loop:
                mov n, ecx;
                push eax;
                push ebx;
                push ecx;
                push edx;
            }
            Extra = pZahlen[n - 1];
            __asm
            {
                pop edx;
                pop ecx;
                pop ebx;
                pop eax;
                mov eax, Extra;
                push eax;
                dec ecx;
                cmp ecx, 0;
                jne push_loop;
                push iAnzahl;
                call durchschnitt;
                mov iDurchschnitt, eax;
                push eax;
                push ebx;
                push ecx;
                push edx;
            }
            Extra = (iAnzahl + 1) * 4;
            __asm
            {
                pop edx;
                pop ecx;
                pop ebx;
                pop eax;
                add esp, Extra;
                pop eax;
                pop ecx;
            }
        }
        printf("Der Durchschnitt: %d\n", (int)iDurchschnitt);
        free((void*)pZahlen);
        getchar();
        getchar();
        return 0;
    }
    


  • Hey! Du bist mein Held und Retter!

    Der Hinweis darauf, dass es mit inline-asm möglich ist, (womit ich mich noch nicht wirklich auseinander gesetzt habe,) hätte mir allein schon vollkommen gereicht.

    Dass du das Ganze auch noch umgesetzt hast setzt dem die Krone auf, vielen vielen Dank! 🙂 Das ist genau das, was ich gesucht habe.

    Das besonders Tolle daran ist, dass ich mich vorher noch nicht mit inline-asm auseinander gesetzt habe und mir das Beispiel erstmal grob gezeigt hat, wie das funktioniert.

    Vielen Dank nochmal!
    Gruß, Volker



  • Naja, wenn es dann unbedingt beliebig viele Parameter sein sollen, sollte man besser die Standard-Library von C benutzen und sich nicht so was mit inline assembler zusammenfrickeln 😉

    #include <stdio.h>
    #include <stdarg.h>
    
    int sumOfArguments(unsigned int numberOfArguments, ...)
    {
    	int sum = 0;
    	unsigned int i = 0;
    	va_list argumentList;
    	va_start(argumentList, numberOfArguments);
    
    	for (i = 0; i < numberOfArguments; ++i)
    		sum += va_arg(argumentList, int);
    
    	va_end(argumentList);
    
    	return sum;
    }
    
    int main()
    {
    	printf("%d\n", sumOfArguments(6, 2, 3, 4, 5, 6, 7));
    
    	return 0;
    }
    

    Gruß
    Don06



  • Hi Don.

    Danke für deine Antwort, aber eventuell hast du meine Frage nicht richtig verstanden. Dein Programm tut nicht das, worum es mir ging 😉

    Trotzdem danke.
    Meine Frage wurde jetzt in allen Belangen beantwortet! 🙂

    Gruß, Volker



  • Upps, du wolltest das zur Laufzeit bestimmen? Ok, sorry 😉



  • Die sinnvolle Loesung waere hier ein Array oder eine Liste zu verwenden. Assembler mag lustig zum rumspielen sein, aber produktiv ist es hier nicht.



  • Hallo.

    @Shade:

    Dazu müsste die Funktion allerdings wissen, wie sie mit einer Liste bzw. einem Array umzugehen hat. Das weiß die Funktion "durchschnitt(int numberOfArguments, ...)" aber nicht und das ist (für mein Verständnis) auch so beabsichtigt. Denn gerade das war ja meine Frage, wie man soetwas bei einer derart vorgegebenen Funktion realisieren kann.

    Wenn ich die Funktion durchschnitt() selbst implementieren müsste, ist mir vollkommen klar, dass ich hierfür Listen, o.ä. verwenden sollte.

    @Don:

    Kein Problem, jede gut gemeinte Antwort freut mich 😉

    Gruß, Volker


Anmelden zum Antworten