Länge eines Arrays bestimmen



  • Ich schreibe gerade an einer Funktion der ein Array übergeben wird, nur kann die größe des Arrays variieren gibt es da ne Funktion dafür die einem die Länge des Arrays zurückgibt?
    Gruß HiFish



  • HiFish schrieb:

    Ich schreibe gerade an einer Funktion der ein Array übergeben wird, nur kann die größe des Arrays variieren gibt es da ne Funktion dafür die einem die Länge des Arrays zurückgibt?
    Gruß HiFish

    Du solltest der Funktion die groesse des Arrays mitgeben.
    Prinzipielle geht das mit sizeof, aber abhaengig vom Kompiler bekommst du dabei probleme. Deshalb solltest du es so machen:

    int main() { int arr[] = { 1, 3, 34, 3};
    int size = sizeof( arr );
    
    function( arr, size );
    return 0;
    }
    


  • void func(int *array, int size);
    
    int main(void)
    {
      int array[10];
      func(array, sizeof(array) / sizeof(array[0]));
      //....
    }
    


  • moe szyslak schrieb:

    Prinzipielle geht das mit sizeof, aber abhaengig vom Kompiler bekommst du dabei probleme.

    falsch. unabhaengig vom compiler sieht eine funktion nur einen pointer aufs erste element und mehr nicht vom uebergebenen array.
    sizeof() ist da nutzlos.

    feigling hat ne gute loesung gepostet. verwende sie, wenn moeglich.



  • jop vielen dank 🙂



  • c.rackwitz schrieb:

    moe szyslak schrieb:

    Prinzipielle geht das mit sizeof, aber abhaengig vom Kompiler bekommst du dabei probleme.

    falsch. unabhaengig vom compiler sieht eine funktion nur einen pointer aufs erste element und mehr nicht vom uebergebenen array.
    sizeof() ist da nutzlos.

    feigling hat ne gute loesung gepostet. verwende sie, wenn moeglich.

    Also mir ist es so schon passiert. Hab ein programm mit gcc 4.0 uebersetzt und auf der Uni ist nur irgendein gcc 3.X installiert.
    Bei mir funktionierte es einwandfrei, auf der Uni nicht!



  • das liegt aber dann nicht unbedingt an einem sizeof auf einen pointer... hast du da die fehlermeldungen noch?



  • moe szyslak schrieb:

    c.rackwitz schrieb:

    moe szyslak schrieb:

    Prinzipielle geht das mit sizeof, aber abhaengig vom Kompiler bekommst du dabei probleme.

    falsch. unabhaengig vom compiler sieht eine funktion nur einen pointer aufs erste element und mehr nicht vom uebergebenen array.
    sizeof() ist da nutzlos.

    feigling hat ne gute loesung gepostet. verwende sie, wenn moeglich.

    Also mir ist es so schon passiert. Hab ein programm mit gcc 4.0 uebersetzt und auf der Uni ist nur irgendein gcc 3.X installiert.
    Bei mir funktionierte es einwandfrei, auf der Uni nicht!

    Dann hattest du Glück im Unglück.

    feigling schrieb:

    ...sizeof(array) / sizeof(array[0])...
    

    Ich verstehe nicht was an dieser Variante so toll ist (da sie ja so oft verwendet wird und viel zu oft falsch 🙄). Schließlich weiß ich doch wie groß mein Array ist, warum sollte ich es dann noch extra ausrechnen...



  • Ganz einfach.

    Sagen wir mal ich habe nen Array von int

    int array[] = {0, 1, 2, 3, 4};
    

    Dann ist die Größe 5.

    Nun benutzen wir das Array sagen wir 20 mal in dem nachfolgenden Quellcode, z.B.

    for(i = 0; i < 5; i++)
      printf("%d\n", array[i]);
    

    Jetzt merken wir aber, dass wir noch etwas ins Array einfügen wollen und ändern

    int array[] = {0, 1, 2, 3, 4};
    

    in

    int array[] = {0, 1, 2, 3, 4, 5};
    

    und ab jetzt sind alle for Schleifen falsch, weil sie das letzte Element nicht bearbeiten. Und bevor man jetzt noch ne Variable mit der Größe anlegt (oder nen define), also

    int array[] = {0, 1, 2, 3, 4, 5};
    int array_len = 6;
    

    und

    for(i = 0; i < array_len; i++)
      printf("%d\n", array[i]);
    

    benutzt, kann man auch gleich sizeof(array) / sizeof(array[0]) benutzen. Ich wüsste nicht, was dadran 🙄 sein soll, wenn man es richtig benutzt.



  • AJ schrieb:

    Ich verstehe nicht was an dieser Variante so toll ist (da sie ja so oft verwendet wird und viel zu oft falsch 🙄). Schließlich weiß ich doch wie groß mein Array ist, warum sollte ich es dann noch extra ausrechnen...

    Stichwort: Redundanz. 😉
    feigling hat ja schon ein Beispiel gepostet.
    Verpack das ganze noch in ein Makro und die Anwendung ist denkbar einfach.
    Jedes mal

    sizeof(array) / sizeof(array[0])
    

    zu schreiben, wäre mir zumindest auch zu nervig.

    moe szyslak schrieb:

    Also mir ist es so schon passiert. Hab ein programm mit gcc 4.0 uebersetzt und auf der Uni ist nur irgendein gcc 3.X installiert.
    Bei mir funktionierte es einwandfrei, auf der Uni nicht!

    Sowas kann auch undefiniertes Verhalten hervorrufen und muss nicht zwangsläufig am Compiler liegen. Wenn du das Programm parat hast, dann zeig es mal her und wir sagen dir, wo der Fehler liegt.



  • @feigling + groovemaster
    Habt ihr beiden eigentlich schon mal was von Konstanten und deren Sinn gehört?

    feigling schrieb:

    Und bevor man jetzt noch ne Variable mit der Größe anlegt (oder nen define),

    "Jetzt noch", ist ja auch zu spät. An sowas sollte man schon beim ersten mal denken.

    Ich sehe in dem Konstrukt mit sizeof() auf jeden Fall eine potenzielle Fehlerquelle, auf die man nicht unbedingt gleich kommt, und erst recht, wenn es auch noch als Makro definiert ist.

    Natürlich bleibts jedem selbst überlassen, wie man es macht, aber empfehlenswerter sind Konstanten.



  • AJ schrieb:

    Natürlich bleibts jedem selbst überlassen, wie man es macht, aber empfehlenswerter sind Konstanten.

    Eher nicht (zumindest für den konkreten Fall). Erstens musst du für jedes Array eine extra Konstante anlegen. Einfach lästig und unnötig. Und zweitens, du musst immer noch darauf achten, dass bei einer Änderung des Arrays die Konstante aktualisiert wird. Klar kannst du die Konstante dafür auch mit dem array / array[0] Konstrukt initialisieren. Nur dann stellt sich die Frage, warum du nicht gleich ein entsprechendes Makro verwendest. Das einzige Problem beim Makro ist, dass du darauf achten musst, dass das Array vorher nicht in einen Zeiger umgewandelt wurde. Aber das ist immer noch unproblematischer, als sich mit Konstanten rumzuschlagen. Und in C++ kann man ja selbst dieses Problem noch eliminieren.



  • groovemaster schrieb:

    Eher nicht (zumindest für den konkreten Fall). Erstens musst du für jedes Array eine extra Konstante anlegen.

    Richtig, das musst du immer:

    ...
    int arr[5]; // => 5 ist auch eine Konstante
    ...
    

    Einfach lästig und unnötig.

    Unbedingt notwendig, siehe oben 😉

    Und zweitens, du musst immer noch darauf achten, dass bei einer Änderung des Arrays die Konstante aktualisiert wird.

    Musst du ja auch immer, siehe wieder oben.

    Klar kannst du die Konstante dafür auch mit dem array / array[0] Konstrukt initialisieren.

    😮 OMG! (Von hinten durch den Rücken ins Knie geschossen...)

    Aber das ist immer noch unproblematischer, als sich mit Konstanten rumzuschlagen. Und in C++ kann man ja selbst dieses Problem noch eliminieren.

    Mir stellt sich grad die Frage, ob du wirklich weißt, wie man Konstanten verwenden sollte.

    Beispiel:

    #define MAX_ZAHLEN 5 //in C++: const MAX_ZAHLEN = 5;
    ...
    arr_zahlen[MAX_ZAHLEN] = {0};
    ...
    for(i = 0 ; i < MAX_ZAHLEN; ++i)
    {
       ...
    }
    ...
    mach_was(arr_zahlen, MAX_ZAHLEN);
    ...
    

    Wenn ich jetzt die Größe des Arrays ändern will, dann brauch ich nur eine einzige Stelle anfassen und der Rest funktioniert trotzdem noch so wie es soll.



  • AJ schrieb:

    Richtig, das musst du immer:

    ...
    int arr[5]; // => 5 ist auch eine Konstante
    ...
    

    Naja, nicht immer. Die ursprüngliche Frage war ja, wie man die Größe bekommt, wenn man das array so anlegt:

    ...
    int arr[] = {1,2,3,...}; 
    ...
    

    Jetzt kann man sich eine Konstante anlegen, um sich die Größe zu merken. Die muss man aber manuell ändern, wenn man die Initialisierung des arrays ändert.
    Oder man machts mit sizeof und muß an diese Änderung nicht mehr denken.

    Warum jetzt die eine Variante fehleranfälliger sein soll als die andere, kann ich im Moment nicht erkennen.



  • AJ schrieb:

    Richtig, das musst du immer:

    ...
    int arr[5]; // => 5 ist auch eine Konstante
    ...
    

    Nein, muss ich nicht. Siehe Guybrush's Post. Zudem sprach ich vielmehr vom Bezeichner der Konstante, also dies hier

    #define MAX_ZAHLEN 5
    

    AJ schrieb:

    Einfach lästig und unnötig.

    Unbedingt notwendig, siehe oben 😉

    Nein. Siehe oben. 😉

    AJ schrieb:

    Und zweitens, du musst immer noch darauf achten, dass bei einer Änderung des Arrays die Konstante aktualisiert wird.

    Musst du ja auch immer, siehe wieder oben.

    Nein. Siehe Posts zuvor.
    Du legst EINMAL! das Makro an und es spuckt IMMER! die korrekte Grösse welchen Arrays auch immer aus. Da kannst du an den Arrays soviel rumschrauben wie du willst. Und irgendwelche Konstanten brauchst du auch nicht anfassen.

    AJ schrieb:

    Klar kannst du die Konstante dafür auch mit dem array / array[0] Konstrukt initialisieren.

    😮 OMG! (Von hinten durch den Rücken ins Knie geschossen...)

    Aber das ist immer noch unproblematischer, als sich mit Konstanten rumzuschlagen. Und in C++ kann man ja selbst dieses Problem noch eliminieren.

    Mir stellt sich grad die Frage, ob du wirklich weißt, wie man Konstanten verwenden sollte.

    Mir stellt sich die Frage, ob du überhaupt weisst, wovon ich rede.

    AJ schrieb:

    Beispiel:

    #define MAX_ZAHLEN 5 //in C++: const MAX_ZAHLEN = 5;
    ...
    arr_zahlen[MAX_ZAHLEN] = {0};
    ...
    for(i = 0 ; i < MAX_ZAHLEN; ++i)
    {
       ...
    }
    ...
    mach_was(arr_zahlen, MAX_ZAHLEN);
    ...
    

    Wenn ich jetzt die Größe des Arrays ändern will, dann brauch ich nur eine einzige Stelle anfassen und der Rest funktioniert trotzdem noch so wie es soll.

    Siehe Antwort zuvor.

    Da ich keine Lust habe mich weiter zu streiten, mach ich dir einen Vorschlag. Nimm eines der Arrays, die hier gepostet wurden (keine eigenen!) und zeige mir mit deinen Konstanten, wie du das Array änderst indem nur EINE! Stelle angepasst wird. Da du sizeof(array) / sizeof(array[0]) offenbar nicht magst, ist das für dich gestorben. Wenn du es mit weniger Anpassungen schaffst als ich, hast du gewonnen. Wenn nicht, dann lässt du es bleiben, und wir haken das ganze unter der Kategorie "auch ein Moderator kann sich irren" ab. Ok?
    Noch ein kleiner Tipp am Rande. Die Chancen, dass du gewinnst stehen ziemlich schlecht, da ich es mit genau EINER! Anpassung schaffe. Und da ich nicht davon ausgehe, dass du übernatürliche Kräfte besitzt, wirst du wohl mehr als 0 Anpassungen benötigen. Das soll dich aber nicht davon abhalten, es trotzdem zu probieren. Also mach dich mal ran...



  • @groovemaster
    Wer redet hier denn von Streit? 😮

    Ich fürchte du steigerst dich da ein wenig zu sehr rein. Nimm dein Makro wie üblich her, mir ist es egal.

    Ich weiß übrigens wovon ich rede und zwar von unterschiedlichen Programmiertechniken.

    Ich nehme das Konstrukt arr[] = { ... } einfach nicht her, dahingehend hab ich nicht das Problem die Größe später noch bestimmen zu müssen, denn ich weiß ja die Größe. Mal ganz davon abgesehen, dass ich es nicht logisch finde erst eine Größe festzulegen und sie dann später wieder ermitteln zu müssen. Auch bei arr[] = { ... } legst du eine feste Größe fest.

    GuybrushThreepwood schrieb:

    Warum jetzt die eine Variante fehleranfälliger sein soll als die andere, kann ich im Moment nicht erkennen.

    Paradebeispiel:

    #define arr_count(a) (sizeof(a)/sizeof(a[0]))
    ...
    int main(void)
    {
       int arr[] = {1, 2, 3};
    
       mach_was(arr);
    }
    
    void mach_was(int * arr)
    {
       printf("%d", arr_count(arr));
    }
    

    Mir ist klar, dass das die meisten nicht machen würden. Weil man schon entsprechende Erfahrung hat. Es geht mir hier aber auch nicht um die Leute, die schon Programmieren (speziell C) können, sondern um die Anfänger. Denn diese verwenden das Makro nicht mit dem nötigen Hintergedanken, weil sie es einfach nicht besser wissen.



  • AJ schrieb:

    Ich nehme das Konstrukt arr[] = { ... } einfach nicht her, dahingehend hab ich nicht das Problem die Größe später noch bestimmen zu müssen, denn ich weiß ja die Größe. Mal ganz davon abgesehen, dass ich es nicht logisch finde erst eine Größe festzulegen und sie dann später wieder ermitteln zu müssen. Auch bei arr[] = { ... } legst du eine feste Größe fest.

    Ja, das hat eine feste Größe, allerdings steht die nicht explizit im Quelltext - und an der Stelle benötigt man das sizeof-Konstrukt, um die Elementanzahl zu bestimmen.



  • groovemaster schrieb:

    Verpack das ganze noch in ein Makro und die Anwendung ist denkbar einfach.
    Jedes mal

    sizeof(array) / sizeof(array[0])
    

    zu schreiben, wäre mir zumindest auch zu nervig.

    Mach's doch lieber als Funktion. Ist schöner *scnr* 🤡



  • CStoll schrieb:

    AJ schrieb:

    Ich nehme das Konstrukt arr[] = { ... } einfach nicht her, dahingehend hab ich nicht das Problem die Größe später noch bestimmen zu müssen, denn ich weiß ja die Größe. Mal ganz davon abgesehen, dass ich es nicht logisch finde erst eine Größe festzulegen und sie dann später wieder ermitteln zu müssen. Auch bei arr[] = { ... } legst du eine feste Größe fest.

    Ja, das hat eine feste Größe, allerdings steht die nicht explizit im Quelltext - und an der Stelle benötigt man das sizeof-Konstrukt, um die Elementanzahl zu bestimmen.

    Wie gesagt, ich rede von unterschiedlichen Programmiertechniken. "Nötig" ist das sizeof-Konstrukt da auch nicht. Nur sinnvoller, wenn man nur eine Stelle anstatt zwei ändern will, mehr aber auch nicht.

    @TactX
    😃



  • @AJ
    Tja, hast dich mehr oder weniger ungekonnt um meinen Vorschlag gedrückt. Sei's drum, kann ja jeder selbst seine Schlüsse ziehen.

    AJ schrieb:

    Ich fürchte du steigerst dich da ein wenig zu sehr rein.

    Keine Sorge, ich steigere mich in nichts hinein. Das Gefühl hatte ich eher von dir. Darf ich dich deshalb daran erinnern, dass DU angefangen hast, gegen dieses sizeof Konstrukt zu wettern. Ich wollte das ganze nur zu einem Abschluss bringen, da es mir sinnlos erscheint, über sowas weiter zu streiten. Zumal feigling bereits eine korrekte Antwort gegeben hat und du mit deinem Einwand dem OP keinen Jota weitergeholfen hast.

    AJ schrieb:

    Ich weiß übrigens wovon ich rede und zwar von unterschiedlichen Programmiertechniken.

    Ach ja? Unter "unterschiedlichen Programmiertechniken" verstehst du, eine Konstante für die Länge eines Arrays zu definieren? Komisch. Ich verstehe darunter zB, ob man strukturiert oder OO programmiert. Aber da haben wir wohl andere Ansichten.

    AJ schrieb:

    Ich nehme das Konstrukt arr[] = { ... } einfach nicht her, dahingehend hab ich nicht das Problem die Größe später noch bestimmen zu müssen, denn ich weiß ja die Größe.

    Nur weil du etwas nicht benutzt, heisst das noch lange nicht, dass andere das auch nicht benutzen.

    AJ schrieb:

    Mal ganz davon abgesehen, dass ich es nicht logisch finde erst eine Größe festzulegen und sie dann später wieder ermitteln zu müssen. Auch bei arr[] = { ... } legst du eine feste Größe fest.

    Ja, das passiert aber für uns implizit durch die Initialisierung. Schon mal daran gedacht, dass für den Programmierer in gewissen Situation die Grösse absolut irrelevant ist? Und man genau deshalb auf solch ein unsized Array zurückgreift? Das Problem ist nur, dass man in gewissen Situationen die Länge halt trotzdem braucht, zB wenn man durch das Array iteriert.

    AJ schrieb:

    Paradebeispiel

    Und einziges Beispiel, das hatte ich aber bereits angesprochen. Zudem ist dies kein Argument für deine Konstanten. Oder verzichtest du generell auf Funktionalität, nur weil es bestimmte Fallstricke gibt? Da frage ich mich doch, warum du überhaupt C programmierst.

    AJ schrieb:

    Wie gesagt, ich rede von unterschiedlichen Programmiertechniken. "Nötig" ist das sizeof-Konstrukt da auch nicht. Nur sinnvoller, wenn man nur eine Stelle anstatt zwei ändern will, mehr aber auch nicht.

    Mehr schon, vor allem wenn es darum geht konsistenten Code zu schreiben. Dort schneided dieses sizeof Konstrukt allgemein besser ab. Nur nochmal zur Verdeutlichung:

    Array anlegen
      mit Konstante
        - Array definieren
        - Konstante definieren
      mit sizeof
        - Array definieren
    Array ändern
      unsized Array
        mit Konstante
          - Arrayinhalt ändern
          - Konstante ändern
        mit sizeof
          - Arrayinhalt ändern
      sized Array
        mit Konstante
          - Arrayinhalt ändern
          - Konstante ändern
        mit sizeof
          - Arrayinhalt ändern
          - Arraygrösse ändern
    

    Wie du siehst, hat man mit Konstante mehr Aufwand, mehr Sorgen und letztendlich mehr verloren als gewonnen.
    Aber im Gegensatz zu dir, will ich niemanden bekehren. Wenn du Konstanten verwenden willst, dann tu das. Aber behaupte nicht, dass es besser sei und man sich wundern solle, dass solche sizeof Konstrukte überhapt, und sehr oft sehr falsch, verwendet werden. Denn das ist schlichtweg Unsinn.

    TactX schrieb:

    Mach's doch lieber als Funktion.

    Keine Sorge, das mach ich. Liegt aber auch daran, dass ich eher C++ programmiere und dann gibts auch keine Fallstricke. 😉


Anmelden zum Antworten