Übergabe von Array an Funktion



  • halli hallo,
    wir (absolute c anfänger!) versuchen seit stunden ein array an eine funktion zu übergeben.

    int myArray[] = {1,40,6,8,9};
    int cnt = sizeof(myArray)/sizeof(int);     //cnt is 5
    maxValue(myArray);
    

    übergeben dieses array dann an die funktion

    int maxValue(int a[])
    {
        for (int i= 0; i<5; i++)
        {
            printf("test %d \n", a[i]);
        }
        int cnt = sizeof(a)/sizeof(int);
    
        [b]printf("cnt: %d \n", cnt);[/b]    //cnt is hier 2
    

    wieso kann die arraygröße in der funktion nicht ermittelt werden?
    sinn und zweck war es, aus einer anzahl von werten den höchsten bzw. den kleinsten zu finden.

    besten dank!!!


  • Mod

    Auch wenn da

    int maxValue(int a[])
    

    steht, so ist das bloß eine andere Schreibweise für

    int maxValue(int *a)
    

    und das a ist eben kein Array mehr, sondern ein Zeiger. Und die Größe eines Zeigers ist in der Regel 4 oder 8, vollkommen unabhängig davon, worauf er zeigt. (Hier zeigt er dann übrigens auf das erste Element des Arrays)

    Eine einfache Gegenmaßnahme ist das Übergeben der Größe in Form eines weiteren Parameters.

    Im Falle von Zeichenketten ist es auch üblich, stattdessen das Ende der Kette mit einem speziellen Zeichen zu markieren (Nullterminierung), da Zeichenkettenfunktionen in der Regel ohnehin nur von ganz vorne bis ganz hinten die Kette durchlaufen und so das Ende erkennen, wenn sie beim (ansonsten nicht erlaubten) Nullzeichen vorbei kommen. Das geht aber nur im Fall von Daten, die sich so ähnlich verhalten wie Zeichenketten.

    wir (absolute c anfänger!) versuchen seit stunden ein array an eine funktion zu übergeben.

    Das klingt komisch. Wie lernt ihr C? Diese Frage sollte eigentlich von jedem brauchbaren Lehrmaterial ziemlich zeitgleich mit der Einführung von Arrays beantwortet werden. Woraus ich folgere, dass ihr entweder ganz ohne Anleitung lernt (schlecht) oder eure Anleitung nichts taugt (noch schlechter, denn dann lernt ihr Falsches, was man nur schwer wieder vergisst). Da solltet ihr etwas dagegen tun.



  • wir haben es versucht mit einem weiteren parameter, allerdings war in der aufgabenstellung nur ein paramater verlangt. mit einem weiteren funktionierte es tadellos.

    siehe aufgabenstellung:

    Implementieren und testen Sie folgende C-Funktionen:
    int maxValue(int a[]); liefert das größte Element der Array zurück
    ...

    wir haben versucht die länge des arrays in einer funktion zu ermitteln. das funktionierte allerdings halt wie oben beschrieben nicht.
    warum ist das nicht möglich die länge des arrays außerhalb der main funktion, wo das array definiert ist zu ermitteln ?



  • warum ist das nicht möglich die länge des arrays außerhalb der main funktion, wo das array definiert ist zu ermitteln ?

    Weil zur Laufzeit keine Informationen über die Größe des Array mitgegeben werden, nur der Zeiger selbst wird übergeben. "sizeof(myArray)" wird daher schon zur Compilezeit vom Compiler ausgewertet und als Konstante einkompiliert.

    Selbst wenn der Compiler es für ein Array auflösen könntem folgendes Problem:

    int maxValue(int a[])
    {
        int size = sizeof(a) / sizeof(int); //Problem, Konstante könnte nicht einmal 10 und einmal 20 sein.
    }
    
    int main()
    {
        int array1[10];
        int array2[20];
    
        maxValue(array1);
        maxValue(array2);
    }
    

    Ergo: Aufgabenstellung ist blöd, vielleicht gingen die von einem immer gleich großen Array aus..



  • Weil zur Laufzeit keine Informationen über die Größe des Array mitgegeben werden

    warum ist das dann in der main methode möglich, die länge herauszufinden?
    findet das nicht zu laufzeit statt?!

    danke schon mal!



  • warum ist das dann in der main methode möglich, die länge herauszufinden?
    findet das nicht zu laufzeit statt?!

    Nein. In C gibt es nach der Kompilierung keine Typinformationen mehr (außer du übergibst sie selbst irgendwie).

    So wird

    int myArray[] = {1,40,6,8,9};
    int cnt = sizeof(myArray)/sizeof(int);
    

    zu

    int myArray[] = {1,40,6,8,9};
    int cnt = 5;
    

    kompiliert. D.h. zur Laufzeit sind nur noch Konstanten vorhanden, "sizeof" hat nur den Zweck dass du die Konstante nicht direkt in den Code schreiben musst sondern der Compiler dir die Berechnung abnimmt. Hat den Vorteil dass du die Konstante bei änderungen nicht manuell umschreiben musst sondern nur neukopilierst.



  • Norben schrieb:

    warum ist das dann in der main methode möglich, die länge herauszufinden?

    Weil in der main-Funktion die Länge separat mit übergeben wird?!
    Weil es dort Vereinbarungen gibt, die besagen, dass mit NULL belegte Elemente als Ende des Arrays anzusehen sind?! (genauso wie bei char-Arrays mit '\0', dann spricht man von Strings)
    Dein Lehrer hat keine Ahnung, wenn er solche Aufgabenstellungen vorgibt.



  • Norben schrieb:

    warum ist das dann in der main methode möglich, die länge herauszufinden?

    Weil das Array (hier) in main definiert wurde. Dadurch ist es eindeutig.

    Noch ein Tipp:
    Statt sizeof(myArray)/sizeof(int); nehmt besser

    sizeof(myArray)/sizeof(myArray[0]);
    //oder 
     sizeof(myArray)/sizeof(*myArray);
    

    Dann braucht ihr euch da keine Gedanken um den Typ zu machen.
    Falls der mal geändert wird, braucht ihr dort keine Anpassung zu machen.

    Wie sieht eure Min/Max-Funktion denn jetzt aus?



  • Wie sieht eure Min/Max-Funktion denn jetzt aus?

    Wir haben die Arraylänge mit übergeben. So funktioniert es. Uns hat nur interessiert, ob es eben auch anders geht, da die Aufgabenstellung lautete:

    Implementieren und testen Sie folgende C-Funktionen:
    int maxValue(int a[]); //liefert das größte Element der Array zurück

    int main(int argc, const char * argv[])
    {	
        int a[] = {200,5,4,3,2,1};
        int cnt = sizeof(a)/sizeof(int);
    
        printf("maxValue: %i \n", maxValue(a,cnt));
    
        return(0);
    }
    
    int maxValue(int a[], int cnt)
    {
        doSort(a,cnt);
        return a[cnt-1];
    }
    

  • Mod

    Fällt euch denn keine wesentlich einfachere Möglichkeit ein, das Maximum einer Reihe Zahlen zu finden, als diese zu sortieren? Wenn ich dir in echt ein paar Karten mit Zahlen* und die gleiche Aufgabe geben würde, wie würdest du vorgehen?

    *: Es sind zu viele Karten, als dass du auf einem Blick das Maximum sehen könntest.



  • SeppJ schrieb:

    Wenn ich dir in echt ein paar Karten mit Zahlen* und die gleiche Aufgabe geben würde, wie würdest du vorgehen?

    Durchblättern und immer die gerade Größte rauslegen, bis eine neue Größere kommt. Also in C die einzelnen Werte in eine Variable legen und immer mit dem nächsten Element vergleichen, falls dieses Größer, die Variable überschreiben?


  • Mod

    Klingt nach einer guten Idee. Versuch das doch mal. Als leicht fortgeschrittenere Aufgabe kannst du auch noch mal darüber nachdenken, welche der beiden Techniken (Sortieren oder die neue Idee) wohl schneller ist und warum.



  • Ist wahrscheinlich effizienter, weil beim Sortieren das Array mehrfach durchlaufen werden muss, bis die Reihenfolge passt und hier das Array nur ein mal durchlaufen wird?

    int maxValue(int a[], int cnt)
    {
        int max;
        for(int i=0 ; i<cnt ; i++)
        {
            if(a[i] > a[i-1])
            {
                max = a[i];
            }
        }
        return max;
    }
    

  • Mod

    Norben schrieb:

    Ist wahrscheinlich effizienter, weil beim Sortieren das Array mehrfach durchlaufen werden muss, bis die Reihenfolge passt und hier das Array nur ein mal durchlaufen wird?

    Ja. Wobei beim Sortieren nicht wirklich von vorne nach hinten durchgelaufen wird, aber insgesamt sind beim Sortieren viel mehr Zugriffe nötig als es Elemente im Array gibt. Beim Maximumsucher, so wie hier, braucht es hingegen nur einen Zugriff pro Arrayelement.

    int maxValue(int a[], int cnt)
    {
        int max;
        for(int i=0 ; i<cnt ; i++)
        {
            if(a[i] > a[i-1])
            {
                max = a[i];
            }
        }
        return max;
    }
    

    Das ist so noch nicht richtig. Sieht zwar auf den ersten Blick so aus, ist es aber nicht.



  • SeppJ schrieb:

    Das ist so noch nicht richtig.

    Achso, okay, da war ein Fehler drin.

    int maxValue(int a[], int cnt)
    {
        int max = 0;
        for(int i=0 ; i<cnt ; i++)
        {
            if(a[i] > max)
            {
                max = a[i];
            }
        }
        return max;
    }
    


  • Was ist, wenn nur negative Zahlen im Array stehen?
    Dann ist max die größte Zahl, obwohl sie gar nicht vorkommt.
    max muss als Initialisierungswert den kleinst möglichen Wert eines ints haben.
    Den bekommst du via INT_MIN aus limits.h.


  • Mod

    Nathan schrieb:

    Was ist, wenn nur negative Zahlen im Array stehen?
    Dann ist max die größte Zahl, obwohl sie gar nicht vorkommt.
    max muss als Initialisierungswert den kleinst möglichen Wert eines ints haben.
    Den bekommst du via INT_MIN aus limits.h.

    Und wenn es sich nicht um ints handelt (Mal angenommen wir schreiben eine typunabhängige Funktion)? Oder wenn das Array leer ist(das betrifft auch den aktuellen Code)? Es gibt da eine bessere Idee für den Anfangswert...



  • SeppJ schrieb:

    Nathan schrieb:

    Was ist, wenn nur negative Zahlen im Array stehen?
    Dann ist max die größte Zahl, obwohl sie gar nicht vorkommt.
    max muss als Initialisierungswert den kleinst möglichen Wert eines ints haben.
    Den bekommst du via INT_MIN aus limits.h.

    Und wenn es sich nicht um ints handelt (Mal angenommen wir schreiben eine typunabhängige Funktion)? Oder wenn das Array leer ist(das betrifft auch den aktuellen Code)? Es gibt da eine bessere Idee für den Anfangswert...

    Stimmt. 👍



  • Okay stimmt, negative Zahlen gibt es auch noch. 🙂

    Mit der limits.h Variante würde ich min einfach INT_MIN zuweisen? (min = INT_MIN;)? Und dahinter verbirgt sich quasi -32768?

    Und wenn es sich nicht um ints handelt (Mal angenommen wir schreiben eine typunabhängige Funktion)? Oder wenn das Array leer ist(das betrifft auch den aktuellen Code)? Es gibt da eine bessere Idee für den Anfangswert...

    Bekomme ich leider nicht heraus. Der restliche Code stimmt aber soweit, es geht nur noch um den Anfangswert?


  • Mod

    Norben schrieb:

    Okay stimmt, negative Zahlen gibt es auch noch. 🙂

    Mit der limits.h Variante würde ich min einfach INT_MIN zuweisen? (min = INT_MIN;)? Und dahinter verbirgt sich quasi -32768?

    Ja. Wobei INT_MIN aber in der Regel wesentlich kleiner sein wird, eher so etwas wie -2 hoch 31.

    Und wenn es sich nicht um ints handelt (Mal angenommen wir schreiben eine typunabhängige Funktion)? Oder wenn das Array leer ist(das betrifft auch den aktuellen Code)? Es gibt da eine bessere Idee für den Anfangswert...

    Bekomme ich leider nicht heraus. Der restliche Code stimmt aber soweit, es geht nur noch um den Anfangswert?

    Letzter Tipp bevor ich es verrate (ja, es ist schwer da drauf zu kommen): Der Anfangswert muss ja nicht der kleinstmögliche Wert überhaupt sein, es muss bloß irgendein Wert sein, von dem du weißt, dass er höchstens so groß ist wie das Maximum in der Menge. Aus welcher Wertemenge könnte solch ein Wert kommen? 😉

    Ansonsten ist der Code soweit richtig. Wenn du drauf kommst, was ein besserer Startwert wäre, ergeben sich ein paar Änderungen von ganz alleine.


Log in to reply