Übergabe einer variablen Zahl von Argumenten



  • 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