Länge eines Array => Wieso falsch??



  • Hi Leute!

    Also ich habe eine Aufgabe bekommen, wo ich eine Fehlerkorrektur machen soll. Nun, einige Fehler konnte ich ausbessern, doch bei einem verstehe ich nicht, wieso es nicht funktioniert. Hier erstmal der Originalcode:

    #include <stdio.h>
    
    int a[] = {0,1,-3,4,-2,9,5,-12,-9};
    
    int main(int argc, char* argv[]) 
    {
      int maximum = 0;
      int i;
    
      for(i = 0; i < sizeof(a); i++)
        if(a[i] > maximum);
    	    maximum = a[i];
    
    	printf("%d\n",maximum);
    }
    

    Und hier meine Überarbeitung:

    #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
      int a[] = {0,1,-3,4,-2,9,5,-12,-9};
      int maximum = 0;
      int i;
    
      for(i = 0; i < 9; i++)
      {
        if(a[i] > maximum)
    	    maximum = a[i];
      }
    	printf("%d\n",maximum);
    	system("Pause");
    }
    

    Das Programm soll den größten Wert des Arrays ausgeben. Nun, das einzigste Problem ist diese Zeile:

    for(i = 0; i < sizeof(a); i++)
    

    Hierbei bekomme ich immer einen astronomisch, hohen Wert heraus. Ersetze ich das "sizeof(a)" aber mit den Anzahl von Indizien des Arrays(9), bekomme ich den größten Wert des Arrays, also das, was ich haben will.
    Ich habe auch gegoogelt, doch überall wird erklärt, dass dieses "sizeof()" die Länge des Array bestimmt. Stimmt das eigentlich(was ich irgendwie nicht glaube)?? Wenn nicht, hat jemand eine Funktion, womit ich die Anzahl der Elemente des Arrays ermitteln kann?? 🙂

    Vielen Dank schon einmal im voraus. 🙂

    MFG Majin_Clodan



  • sizeof(a) gibt dir die Bytes des gesamten Arrays, nicht wieviele Einträge es hat. Benutze sizeof(a) / sizeof(a[0]), um an die Anzahl der Einträge zu kommen.



  • sizeof() bestimmt auch die Länge des Arrays, allerdings in Byte. Wenn du die Anzahl Elemente bestimmen willst, musst du die Bytezahl durch die Anzahl Bytes für ein Element teilen:
    sizeof(a) / sizeof(a[0]);



  • Nach meines Wissens bestimmt sizeof() die größe des reservierten Speichers in Bytes.

    Als überprüfung kannst du mal spaßeshalber die größe ausgeben...

    Mfg
    Singh



  • schau dir mal std::vector an



  • Den sizeof -Operator würde ich nicht verwenden, um bei Arrays die Grösse zu bestimmen. Wenn man nämlich Arrays an Funktionen übergibt, ist die Information auch verloren.

    Also entweder, wenn man unbedingt mit rohen Arrays arbeiten will, speichert man sich die Grösse separat ab, oder, was die schönere Lösung darstellt, man verwendet Container wie std::tr1::array oder std::vector .



  • @Nexus:
    Mit fällt auf dass du öfters Dinge schreibst, die, ... naja einfach falsch sind.

    Nexus schrieb:

    Den sizeof -Operator würde ich nicht verwenden, um bei Arrays die Grösse zu bestimmen. Wenn man nämlich Arrays an Funktionen übergibt, ist die Information auch verloren.

    Man kann in C++ keine Arrays an Funktionen übergeben. Man kann zwar Dinge schreiben wie

    void foo(int a[10])
    {
        // ...
    }
    

    bloss das ist nur eine alternative Schreibweise für

    void foo(int* a)
    {
        // ...
    }
    

    In beiden Fällen hat a den Typ "int*". Man kann sogar den Prototyp als "int a[10]" schreiben, und die Funktion dann mit "int* a" implementieren - beide Schreibweisen sind 100% äquivalent; was die Bedeutung angeht. Was die Verständlichkeit angeht ist die "int* a" Variante zu bevorzugen, da so klar wird dass a nur ein Zeiger ist, und auch keine "Grösse" hat.

    Nur nochmal damit es da kein Misverständnis gibt: du kannst einen Zeiger auf einen einzelnen int an so eine "int a[10]" Funktion übergeben - jeder Compiler wird das akzeptieren, da diese Schreibweise wie gesagt 100% äquivalent zu "int* a" ist -- die "Grösse" (10 in diesem Beispiel) wird dabei vom Compiler total ignoriert. Die Array-Schreibweise macht nur dann einen Sinn wenn man mehrdimensionale Arrays verwendet. Auch in dem Fall wird allerdings nur ein einfacher Zeiger übergeben, und es verschwindet die Information über die grösse der "letzten" Dimension.

    Und dann bleibt nurnoch die Möglichkeit Referenzen auf Arrays zu übergeben ("int (&a)[10]"). Bei dieser Variante bleibt die Information über die Grösse dann auch erhalten, und man kann sie auch nicht mit "unpassenden" Arrays bzw. einzelnen int Variablen aufrufen.

    ----

    Davon abgesehen ist es IMO guter Stil die Grösse von Arrays über den sizeof Operator zu bestimmen. Arrays haben nunmal eine fixe Grösse, und diese bekommt man damit zuverlässig raus. Irgendwelche Konstanten zu verwenden ist einfach "anfälliger", da es schnell mal passiert dass so eine Konstante nicht korrekt mit angepasst wird, und dann einfach nen falschen Wert hat.



  • Tut mir leid, das was du erklärt hast, war mir eigentlich schon bewusst - ich habe mich nur wieder mal schlecht ausgedrückt. 🙄

    Das mit der Übergabe von Array als Referenzen braucht bei unbekannter Grösse Templates, von daher dachte ich, dass das für den Anfänger nicht gerade relevant sei. Zumal dieser oft Arrays "direkt" an Funktionen übergibt, also als Zeiger. Und weil es schon sehr viele Leute gab, die sich fragten, warum sizeof(Array) in der Funktion immer 4 wäre, dachte ich, es wäre für den Anfang besser, nicht immer den sizeof -Operator zu empfehlen.

    Naja, wie auch immer, ich denke wir sind uns einig, dass Container die bessere Möglichkeit darstellen. 😉



  • hustbaer schrieb:

    Man kann in C++ keine Arrays an Funktionen übergeben. Und dann bleibt nurnoch die Möglichkeit Referenzen auf Arrays zu übergeben ("int (&a)[10]"). Bei dieser Variante bleibt die Information über die Grösse dann auch erhalten, und man kann sie auch nicht mit "unpassenden" Arrays bzw. einzelnen int Variablen aufrufen.

    oh, das führt ja direkt zu

    //normale funktion
    foo(int* a,size_t size)
    {//wasauchimmer
    }
    
    //wrapper für faule
    template<size_t size> foo(int (&a)[size])
    {
       foo(a,size);
    }
    

    Davon abgesehen ist es IMO guter Stil die Grösse von Arrays über den sizeof Operator zu bestimmen.

    Ja! 👍



  • volkard schrieb:

    oh, das führt ja direkt zu

    //normale funktion
    foo(int* a,size_t size)
    {//wasauchimmer
    }
    
    //wrapper für faule
    template<size_t size> foo(int (&a)[size])
    {
       foo(a,size);
    }
    

    Ungewöhnlich finde ichs nicht. Wurde das schon zum Idiom erhoben?

    Dazu am Rande: Seit constexpr freue ich mich in C++0x auf ein potentielles

    template< typename Type, size_t N >
    constexpr size_t countof( Type ( &array )[ N ] )
    {
         return N;
    }
    


  • Nexus schrieb:

    Und weil es schon sehr viele Leute gab, die sich fragten, warum sizeof(Array) in der Funktion immer 4 wäre, dachte ich, es wäre für den Anfang besser, nicht immer den sizeof -Operator zu empfehlen.

    Gerade aus dem Grund finde ich es wichtig, bei Fragen von Anfängern, darauf hinzuweisen, dass man in C++ garkeine Arrays an Funktionen übergeben kann. 😉

    Speziell weil die Syntax so aussieht, als ob hier das Array kopiert würde, was ja nicht der Fall ist. Wenn man sich darauf verlässt, dass das Array kopiert wird, wird man sich schnell wundern, warum das Programm nicht das tut was man denkt. z.B. wenn man "ein Array an eine Funktion übergibt", die dieses intern ändert, und sich dann wundert warum das Original sich auch geändert hat.



  • Ich hab mal gelernt, wenn das Array z.B.zum alleinigen Mitglied einer Struktur(POD)
    gemacht wird, kann man es an eine Funktion übergeben - indem man die Struktur übergibt.
    😃
    Prost!



  • hustbaer schrieb:

    Gerade aus dem Grund finde ich es wichtig, bei Fragen von Anfängern, darauf hinzuweisen, dass man in C++ garkeine Arrays an Funktionen übergeben kann. 😉

    Hm, das stimmt schon. Aber da kommt wieder eine Begrifflichkeit ("Übergabe") ins Spiel. Grundsätzlich wäre es eh besser, Anfänger würden nicht zu früh mit Arrays konfrontiert. Denn um Arrays zu verstehen, muss man auch die Funktionsweise von Zeigern und Zeigerarithmetik begriffen haben.

    POD PUNSCH schrieb:

    Ich hab mal gelernt, wenn das Array z.B.zum alleinigen Mitglied einer Struktur(POD)
    gemacht wird, kann man es an eine Funktion übergeben - indem man die Struktur übergibt.

    Anstatt sich für jeden Fall eine eigene Struktur zu basteln, kann man eben auch std::tr1::array benutzen, da hat man einen simplen Array-Wrapper, der im Gegensatz zur struct auch STL-kompatibel ist.



  • Nexus schrieb:

    hustbaer schrieb:

    Gerade aus dem Grund finde ich es wichtig, bei Fragen von Anfängern, darauf hinzuweisen, dass man in C++ garkeine Arrays an Funktionen übergeben kann. 😉

    Hm, das stimmt schon. Aber da kommt wieder eine Begrifflichkeit ("Übergabe") ins Spiel.

    Damit hast du wohl Recht. Für mich ist der Begriff ganz klar, was aber natürlich nicht heisst, dass jeder andere auch dasselbe darunter versteht.

    Und ich muss mir auch eingestehen, dass ich selbst manchmal Dinge wie "als Referenz übergeben" sage, was meinem eigentlichen Verständnis des Begriffs "etwas an eine Funktion übergeben" widerspricht (richtig wäre für mich "eine Referenz auf ... übergeben", was aber länger ist, und weil man eben faul ist...).


Anmelden zum Antworten