array als parameter?



  • Ich kapier das nicht mit den Pointern.

    Warum werden Arrays bei Funktionen als Pointer übergeben?

    Bevor eine Funktion aufgerufen wird, müssen die Parameter irgendwohin geschrieben werden. Das ist der Stack und/oder die CPU-Register. Dort wird eine Kopie des Wertes abgelegt.
    Da der Platz dort begrenzt ist und Arrays doch recht groß werden können geht man den Umweg über Pointer. Der Pointer zeigt also auf den Speicherbereich vom Array.
    Daher kann die Funktion diesen Bereich auch ändern.

    Den Rückgabewert einer Funktion (mit return ?) kannst du einer Variablen zuweisen oder damit weiterrechnen. Der Typ des Wertes wird bei der Funktionsdeklaration bekannt gegeben.



  • Schau dir doch mal meinen Code von 16:31:12 an und was bei dir steht.

    Nochmal: Das was du mit return zurückgibst musst du dann auch mit

    int *abc;
    abc = zahlen_einlesen(v, n)
    

    zuweisen.

    Wobei abc natürlich vom richtigen typ sein soll
    oder mit

    zahlen_ausgeben(zahlen_einlesen(v, n), n);
    

    verarbeiten



  • Hm, ok!

    Jetzt weiß ich was da jetzt falsch war. Jetzt sieht der Code so aus:

    #include<stdio.h>
    
    int* zahlen_einlesen(int v[], int n)
    {
    	int i;
    	int hilfsvar;
    	for(i=0; i<n; i=i+1);
    	{
    		scanf("%i", &hilfsvar);
    		v[i] = hilfsvar;
    	}
    	return v;
    }
    
    void zahlen_ausgeben(int v[], int n)
    {
    	int i;
    	for(i=0; i<n; i=i+1);
    	{
    		printf("%i\n", v[i]);
    	}
    }
    
    int main()
    {
    	int v[50], n;
    
    	printf("n eingeben: "); scanf("%i", &n);
    
    	zahlen_einlesen(v, n);
    	/*zahlen_ausgeben(v, n);
    	zahlen_sortieren(v, n);
    	zahlen_ausgeben(v, n);*/
    
    return 0;
    }
    

    Jetzt hab ich aber das Problem, dass nach der Eingabe von n (also die Abbruchbedingung für die for-Schleife in der Funktion zahlen_einlesen) ich nur eine einzige Zahl eingeben kann und dann das Programm sofort zum return 0; in der main springt. Wenn ich es im Debugger beobachte, ist nach dem aufruf der for-Schleife in der Funktion i=5! Im Kopf der for-Schleife setze ich aber i = 0! Und das verstehe ich schon gleich gar nicht. Die Variable i ist doch nur eine in der Funktion gültige Variable! Die kann doch dann noch von nem Pointer verändert werden, oder hat das doch wieder was mit Pointern zu tun? Wie geht'n das jetzt? Was ist da jetzt falsch?



  • for(i=0; i<n; i=i+1); // ist eine Leerschleife
    //                  ^ wegen Semikolon hier
    

    Der Compiler optimiert halt 😃



  • Verdamm** Sche***! Warum fällt mir das nicht auf?

    So, aber nichts destotrotz scheints jetzt zu funktionieren:

    #include<stdio.h>
    
    #define TRUE 1
    #define FALSE 0
    
    int* zahlen_einlesen(int v[], int n)
    {
    	printf("Zahlen fuer Liste eingeben:\n");
    	int i;
    	int hilfsvar;
    	for(i=0; i<n; i=i+1)
    	{
    		scanf("%i", &hilfsvar);
    		v[i] = hilfsvar;
    	}
    	return v;
    }
    
    void zahlen_ausgeben(int v[], int n)
    {
    	printf("Ausgabe der Zahlen: ");
    	int i;
    	for(i=0; i<n; i=i+1)
    	{
    		printf("%i", v[i]);
    	}
    	printf("\n");
    }
    
    void zahlen_sortieren(int v[], int n)
    {
    	int i, h;
    	int sortiert;
    
    	do
    	{
    		sortiert = TRUE;
    		for(i=0; i<n-1; i=i+1)
    		{
    			if(v[i+1] < v[i])
    			{
    				h = v[i];
    				v[i] = v[i+1];
    				v[i+1] = h;
    				sortiert = FALSE;
    			}
    		}
    	}while(sortiert == FALSE);
    }
    
    int main()
    {
    	int v[50], n;
    
    	printf("n eingeben: ");
    	scanf("%i", &n);
    
    	zahlen_einlesen(v, n);
    	zahlen_ausgeben(v, n);
    	zahlen_sortieren(v, n);
    	zahlen_ausgeben(v, n);
    
    return 0;
    }
    


  • Noch eine Frage:

    Könnte man die Funktion zahlen_einlesen, auch so programmieren, dass man keinen return-Wert benötigt? Wie würde das gehen?

    Der Funktionskopf müsste doch dann irgendwie so aussehen:

    void zahlen_einlesen(int v[], int* n)
    {
    	printf("Zahlen fuer Liste eingeben:\n");
    	int i;
    	int hilfsvar;
    	for(i=0; i<n; i=i+1)
    	{
    		scanf("%i", &hilfsvar);
    		v[i] = hilfsvar;
    	}
    }
    

    Ist das soweit richtig? Probleme gibts so jetzt natürlich noch beim n in der for-Schleife, da ja ein int i mit dem int *n verglichen wird.



  • bandchef schrieb:

    void zahlen_einlesen(int v[], int* n)
    

    Wo kommt denn <int* n> schon wieder her? In der vorigen Version hast du doch schon halbwegs alles korrekt gehabt inkl. Rückgabe des int*.
    Um dein int-Array zu befüllen, brauchst du das int-Array selbst nicht zu verändern sondern nur dessen Elemente. Außer der Arraygröße brauchst du nichts weiter zu übergeben.
    Für die Verwendung im aufrufenden Kontext ist es aber einfacher (und wird auch von vielen Standardfunktionen so implementiert), das geänderte Argument als Rückgabewert nochmals zu verwenden,

    zahlen_ausgeben(zahlen_eingeben(...))
    

    ist bequemer als

    int *a;
    zahlen_eingeben(a,...);
    zahlen_ausgeben(a);
    


  • @Wutz:

    Ich bin auf das

    void zahlen_einlesen(int v[], int* n)
    

    gekommen weil in meinem Buch (Programmieren lernen mit C von Karlz-Heinz Zeiner) eben die Aufgabe gestanden hat:

    Schreiben Sie den Programmcode für die Funktionen zahlen_einlesen und zahlen_ausgeben. Die einzelnen Funktion sind in einer Datein in folgender Reihenfolge anzuführen:

    #include<stdio.h>
    
    void zahlen_einlesen(int v[], int *n)
    {
     ...
    }
    
    void zahlen_ausgeben(int v[], int n)
    {
     ...
    }
    
    void zahlen_sortieren(int v[], int n)
    {
     ...
    }
    
    int main()
    {
     ...
    }
    

    Beachte bitte bei der Aufgabenstellung den ersten Funktionskopf:

    void zahlen_einlesen(int v[], int *n)
    {
     ...
    }
    

    Der Funktionkopf meines, deiner Aussage nach, "halbwegs funktionierenden Programms" lautet aber so:

    int* zahlen_einlesen(int v[], int n)
    {
     ...
    }
    

    Ist da nun ein Fehler im Buch? Oder wie? Das komische daran ist halt, dass ich in dieser Aufgabe mit return-Werten hantieren muss, obwohl dazu bisher im Buch noch kein einziges Wort gefallen ist und erst auf den nächsten Seiten auftaucht. Soll ich das hier als bekannt vorraussetzen, oder wie?



  • 1. Wie schon mehrfach gesagt brauchst du das return nicht. Dann ist die Funktion aber auch vom Typ void. Also Zeile mit return löschen und void

    2. Vielleicht erwartet dein Buch die Eingabe von n nicht in main sondern in zahlen_einlesen(). Und dann muss ja main irgendwie wissen wie viele Zahlen eingelesen wurden.

    void zahlen_einlesen(int v[], int *n)
    {
        printf("n eingeben: ");
        scanf("%i", n);   // ohne & denn n ist schon ein Zeiger
    
        printf("Zahlen fuer Liste eingeben:\n");
        int i;
        int hilfsvar;
        for(i=0; i<*n; i=i+1)  // *n ist wie ein int
        {
            scanf("%i", &hilfsvar);
            v[i] = hilfsvar;
        }
    }
    


  • Danke für deine Antwort.

    Ich hab mir jetzt eine neue Aufgabe gebastelt. Diesesmal beschränke ich mich aber auf genau 3 Zahlen. Hier hab ich jetzt das Problem, dass mir der Compiler meldet, dass der Stack um die Variable array beschädigt sei. Ich weiß aber wiedermal nicht was da jetzt falsch sein soll.

    #include<stdio.h>
    
    int* zahl_einlesen(int a, int array[])
    {
    	for(int i=0; i<a; i=i+1)
    	{
    		int zahl;
    		scanf("%i", &zahl);
    		array[i] = zahl;
    	}
    	return array;
    }
    
    void zahl_sortieren(int a, int array[])
    {
    	int hilfsvar = 0;
    	int j = 0;
    
    	while(j != a)
    	{
    		for(int i=0; i<a; i=i+1)
    		{
    			if(array[i] > array[i+1])
    			{
    				hilfsvar = array[i];
    				array[i] = array[i+1];
    				array[i+1] = hilfsvar;
    			}
    		}
    		j = j + 1;
    	}
    }
    
    void zahl_ausgeben(int a, int array[])
    {
    	for(int i=0; i<a; i=i+1)
    	{
    		printf("%i", array[i]);
    	}
    }
    
    int main()
    {
    	int b, array[3];
    
    	b = 3;
    
    	zahl_einlesen(b, array);
    	zahl_sortieren(b, array);
    	zahl_ausgeben(b, array);
    
    return 0;
    }
    


  • void zahl_sortieren(int a, int array[])
    {
        int hilfsvar = 0;
        int j = 0;
    
        while(j != a)
        {
            for(int i=0; i<a; i=i+1)
            {
                if(array[i] > array[i+1]) // wenn i = 2 ist was ist dann i+2
                {
                    hilfsvar = array[i];
                    array[i] = array[i+1]; // und bis wohin geht das array?
                    array[i+1] = hilfsvar;
                }
            }
            j = j + 1;
        }
    }
    


  • Danke!

    Die Lösung lautet dann wohl:

    void zahl_sortieren(int a, int array[])
    {
        int hilfsvar = 0;
        int j = 0;
    
        while(j != a)
        {
            for(int i=0; i<(a-1); i=i+1)
            {
                if(array[i] > array[i+1]) // wenn i = 2 ist was ist dann i+2
                {
                    hilfsvar = array[i];
                    array[i] = array[i+1]; // und bis wohin geht das array?
                    array[i+1] = hilfsvar;
                }
            }
            j = j + 1;
        }
    }
    


  • Soll heissen, dass du über die Arraygrenzen hinaus auf Speicherbereiche zugreifst, was undefiniertes Verhalten bedeutet und du froh sein kannst, wenn der Programmlauf dir dies auch noch mitteilt. (wahrscheinlich baut dein Compiler entsprechenden Grenzprüfungscode ein)



  • Er wird noch die Debug-Umgebung haben.

    @bandchef
    Und die Warnung kam sicher nicht vom Compiler sondern erst zu Laufzeit (vom Debugger?)


Anmelden zum Antworten