Länge eines Arrays



  • Sqwan schrieb:

    sizeof()
    

    sollte gehen
    ggf auch:

    sizeof(array) / sizeof(char)
    

    EDIT:
    Kleine recherche bei google:
    strlen() soll für char-arrays funktionieren...

    besser wär

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

    falls das überhaupt klappt 😉



  • Danke, ja das zweite mit dem ersten Element als Divisor gefällt mir noch besser da ich hier unabhängig vom typ bin. strlen war mir bekannt funktioniert aber nur bei 0 terminierten Strings und das hätte bei dem Beispiel falsche Werte gebracht.


  • Mod

    Da ich die nächste Frage erraten kann, beantworte ich sie schon einmal:
    Nein, das funktioniert, wenn man nur einen Zeiger auf ein Array hat (zum Beispiel nach Übergabe an eine Funktion). In diesem Fall würde man bloß die Länge eines Zeigertyps erhalten (gewöhnlich 4 oder 8).



  • @SeppJ du meintest die größe des arrays muß zu compilezeit feststehen? da sonst sizeof nicht klappt? hab das iwie noch nicht so ganz verstanden 😞



  • nachfrager schrieb:

    @SeppJ du meintest die größe des arrays muß zu compilezeit feststehen? da sonst sizeof nicht klappt? hab das iwie noch nicht so ganz verstanden 😞

    Nein, die Größe muss zur Compilezeit nicht feststehen (C99 VLAs gehen mit sizeof auch). Man muss eben nur beachten, dass man hier einen der wenigen Fälle hat, wo eine Unterscheidung zwischen Array und Pointer eine Rolle spielt. In C wird das ja sonst nicht so eng genommen.


  • Mod

    nachfrager schrieb:

    @SeppJ du meintest die größe des arrays muß zu compilezeit feststehen? da sonst sizeof nicht klappt? hab das iwie noch nicht so ganz verstanden 😞

    Komplett anderes Thema, klare Antwort: Jain. 😃

    Erstmal hat das Funktionieren von sizeof nichts damit zu tun. sizeof liefert die Größe der Variablen. Wirft man sizeof ein Array vor, bekommt man die Größe des Arrays, nimmt man einen Zeiger, bekommt man die Größe des Zeigers, ganz einfach. Worauf ich hinaus wollte ist, dass man öfters mal Konstrukte hat wie

    void foo(int *bar);
    
    // ...
    
    int beispiel[5];
    foo(beispiel);
    

    Dann könnte foo() nicht feststellen, dass das übergebene Array 5 Elemente hat, weil sizeof ja bloß die Größe des Zeigers bar liefern würde.

    Nun zu der Frage ob Arraygrößen zur Compilezeit feststehen müssen:
    Zunächst einmal Nein, denn man kann immer mit malloc Arrays beliebiger (zur Compilezeit unbekannter) Größe anlegen*. Dann aber auch wieder ja, denn wenn man nicht mit malloc arbeitet (also zum Beispiel int beispiel[5]; ) dann muss die Größe, hier 5, zur Compilezeit feststehen.
    Man sollte auch sagen, dass einige Compiler (zum Beispiel GCC) bei letzterem auch Werte akzeptieren die zur Compilezeit noch nicht bekannt sind. Dies sind aber nicht standardisierte Compilererweiterungen. Deshalb lieber nicht in wichtigem Code benutzen. Ist aber ganz praktisch für schnell zusammengeschriebene Testprogramme.

    *: Ganz genau genommen hat man dann aber bloß einen Zeiger auf einen Speicherbereich, den man wie ein Array benutzt, kein Array im Sinne des Typensystems. Entsprechend kann man auch hier im Nachhinein nicht mittels sizeof feststellen, wie groß der Speicherbereich ist, man bekommt nur die Größe des Zeigers.



  • erklärs doch noch komplizierter...

    Wenn man ein array an eine funktion übergibt, wird nur ein Zeiger auf das array übergeben. Und wenn man die größe mit sizeof() nun bestimmt wird die größe des Zeigers in Byte zurück gegeben. Bei mir sinds 4Byte...
    Also 32 bit. Eigentlich nur eine Zahl die angibt an welcher stelle im speicher der erste wert beginnt.

    EDIT: Bezog sich auf rüdigers beitrag. hast es gut erklärt ^^
    EDIT2: Ist c++ weil ich keinen reinen c-kompiler habe... bzw ich weiß nicht obs in c auch ginge. Ist vllt auch nicht schön, aber bei mir funktionierts so auch:

    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    void test(char a[])
    {
         printf("%i\n", sizeof(a));
    }
    int main(int argc, char *argv[])
    {
        char arrays[32] = "";
        printf("%i\n", sizeof(arrays));
        test(arrays);
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    reicht ja wenn ihr die funktion betrachtet. ergebnis ist 32 und 4



  • Hmm schade das sizeof nach der Übergabe an eine Funktion nicht mehr klappt. Ich hatte nämlich vor in meiner Funktion erstmal zu überprüfen ob die Parameter ausreichend dimensioniert sind damit meine Funktion kein undefiniertes Verhalten erzeugt.

    Wie löse ich sowas dann? Ich möchte ein char* str prüfen ob darin z.B. 32 Zeichen Platz hätten. Muss ich dann die Länge vorher mit sizeof bestimmen und dann als zusätzlichen Parameter mit übergeben oder wie lösen die Profis sowas?

    Macht es einen Unterschied ob ich char* str übergebe oder char atr[] ?



  • whitespaces schrieb:

    Hmm schade das sizeof nach der Übergabe an eine Funktion nicht mehr klappt. Ich hatte nämlich vor in meiner Funktion erstmal zu überprüfen ob die Parameter ausreichend dimensioniert sind damit meine Funktion kein undefiniertes Verhalten erzeugt.
    Wie löse ich sowas dann? Ich möchte ein char* str prüfen ob darin z.B. 32 Zeichen Platz hätten. Muss ich dann die Länge vorher mit sizeof bestimmen und dann als zusätzlichen Parameter mit übergeben oder wie lösen die Profis sowas?

    Die Profis nehmen oftmals Arrays eben wegen der vorgegebenen festen Größe nicht. (C89) Viele Programme sind parametrisierbar, da verbietet es sich dann.
    Das gilt auch für lokale nichtstatische Arrays, die selbst bei geringer Dimensionierung gerne mal einen Stacküberlauf produzieren (natürlich immer erst unter Einsatzbedingungen und nicht etwa während der Entwicklung 🙂 ).
    Den Vorzug haben dynamische, d.h. bei Bedarf größenmäßig erweiterbare Datenstrukturen. Und hierfür hat man üblicherweise Eigenentwicklungen für die Kapselung von *alloc/free oder man verwendet, wenn man mit den Lizenzen klarkommt, praktisch erprobte Frameworks, z.B. glib.

    Für deinen Fall, und wenn du auf Arrays verzichtest und dyn.Speicher übergibst und MSVC/MinGW verwendest, wäre z.B. möglich:

    #include <malloc.h>
    #ifndef __int64
    #error such dir was anderes
    #endif
    
    void f(char *s)
    { printf("%lu\n", _msize(s)); }
    
    main() {
    f(malloc(4711));
    return 0;
    }
    

    oder Beispiel für Holzhammer aber strikt C89:

    char *strErweitern(char *s,const char *anhang)
    {
      s=realloc(s,strlen(s)+1+strlen(anhang));
      if(!s) ...
      return strcat(s,anhang);
    }
    
    main() {
    char *s;
    puts(s=strErweitern(strcpy(malloc(5),"1234"),"567890")); free(s);
    return 0;
    }
    

    whitespaces schrieb:

    Macht es einen Unterschied ob ich char* str übergebe oder char atr[] ?

    Nein. Nur das es knallt, wenn du ein sich hinter einem Zeiger versteckendes Array übergibst und in der Funktion dann versuchst, den Speicherbereich zu vergrößern.



  • Dankeschön für die sehr ausführliche Erklärung. Ich werde dann mal was eigenes schreiben für die dynamische Speicherverwaltung, hier gab es ja auch einen guten Artikel wie man das macht. http://www.c-plusplus.net/forum/viewtopic-var-p-is-1463522.html


Anmelden zum Antworten