Mehrdimensionales Array an Funktion übergeben



  • Ich denke, es ist sehr hilfreich, wenn man das mal "aufmalt".

    void foo(int *x[]);
    
               Array aus
    Zeiger      Zeigern
               +------+
      x -----> | x[0] |----> ? ? ? ... (ein int oder mehrere 
               |------|                 hintereinander im Speicher)
               | x[1] |----> ? ? ? ...
               |------|
               | x[2] |----> ? ? ? ...
               +------+
               :      :
    
    wobei zu
    void foo(int x[][3]);
    folgendes Bildchen gehört
    
                   Array aus
    Zeiger     Arrays von 3 ints
               +---------------+
      x -----> | x[0]: [? ? ?] |
               |---------------|
               | x[1]: [? ? ?] |
               |---------------|
               | x[1]: [? ? ?] |
               +---------------+
               :               :
    

    wobei ? jeweils für einen int steht, welche im letzten Fall alle hintereinander im Speicher angeordnet sind, also x[0][1] steht hinter x[0][0], x[1][0] steht hinter x[0][2], u.s.w.

    edit: Tippfehler 5 in 3 geändert



  • ok dazu habe ich nochmal ein paar Fragen. Erstmal wieso "5 ints "? SInd es nicht nur 3?

    Dann das man für Stringtabellen

    void foo(int *x[]);
    

    verwndet erscheint mir logisch, mann weis ja nicht wie lang die einzelnen Strings sind.

    Aber warum muss man bei der Übergabe mehrdimensionaler Arrays

    void foo(int x[][3]);
    

    verwenden. Liegt das nur am Zerfallsverhalten bei der Übergabe?

    Aber wieso ist beim ersten die Übergabe der Länge nicht erforderlich? Wenn man sie doch beim 2. unbedingt zum berechnen braucht.


  • Mod

    Max123 schrieb:

    ok dazu habe ich nochmal ein paar Fragen. Erstmal wieso "5 ints "? SInd es nicht nur 3?

    Sebastian Pizer war in seinem Schaublid anscheinend zu faul, alle 5 hin zu malen und hat sich mit 3 begnügt um das Prinzip zu zeigen. Aber int[5] sind nun mal 5 ints.

    Dann das man für Stringtabellen

    void foo(int *x[]);
    

    verwndet erscheint mir logisch, mann weis ja nicht wie lang die einzelnen Strings sind.

    Aber warum muss man bei der Übergabe mehrdimensionaler Arrays

    void foo(int x[][3]);
    

    verwenden. Liegt das nur am Zerfallsverhalten bei der Übergabe?

    Mach dir nochmal den Unterschied klar: Das erste ist ein Array von Zeigern, das zweite ist ein Array von Array. Das sind ganz verschiedene Dinge! Sebastian Pizers Bild zeigt das schon genau wie es ist, mehr kann man da eigentlich nicht erklären. Guck dir das noch mal an!

    Aber wieso ist beim ersten die Übergabe der Länge nicht erforderlich? Wenn man sie doch beim 2. unbedingt zum berechnen braucht.

    Nochmal: Wenn man ein Array hat, muss man irgendwie berechnen können, wo array[0], array[1], array[2], usw. tatsächlich im Speicher liegen. Dazu muss man wissen, wie lang jedes einzelne Element ist, es ist aber egal, wie viele Elemente das Array selber hat.
    Wenn man nun ein Array von Arrays hat, dann muss man wissen, wie viele Elemente die inneren Arrays haben, damit man weiß, wie lang die Elemente des äußeren Arrays sind.



  • Max123 schrieb:

    ok dazu habe ich nochmal ein paar Fragen. Erstmal wieso "5 ints "? SInd es nicht nur 3?

    Tippfehler von mir.

    Max123 schrieb:

    Aber wieso ist beim ersten die Übergabe der Länge nicht erforderlich? Wenn man sie doch beim 2. unbedingt zum berechnen braucht.

    Du hast anscheinend den Unterschied zwischen Zeiger und Array nicht verstanden. Wie gesagt, der Elementzugriff ist syntaktisch derselbe. Trotzdem ist ein Zeiger etwas anderes als ein Array.

    Gruß,
    SP



  • Ok ich glaube ich habs jetzt verstanden.

    void foo(int *x[]);
    

    bei dem Array aus Zigern ist die Größe ja durch die Zeigerart festgelegt, also bekannt.

    Beim Array aus Arrays hängt die Größe der Elemente des äußeren Arrays jedoch von der Element Anzahl der inneren ab- Deshalb muss diese bekannt sein.

    Nur noch eine Frage wieso kann ich mehrdimensionale Arrays nicht an eine Funktion übergeben, indem ich mit

    void foo(int *x[]);
    

    einen Zeiger auf ein Zeigerarray übergebe?



  • Max123 schrieb:

    bei dem Array aus Zigern ist die Größe ja durch die Zeigerart festgelegt, also bekannt.

    Beim Array aus Arrays hängt die Größe der Elemente des äußeren Arrays jedoch von der Element Anzahl der inneren ab- Deshalb muss diese bekannt sein.

    Das ist ein Bingo! 😉

    Max123 schrieb:

    Nur noch eine Frage wieso kann ich mehrdimensionale Arrays nicht an eine Funktion übergeben, indem ich mit

    void foo(int *x[]);
    

    einen Zeiger auf ein Zeigerarray übergebe?

    Hmm... Das sitzt noch nicht 100%. Also nochmal: Array != Zeiger

    Deine Frage ist: Warum kann die Funktion foo

    void foo(int *x[]);
    

    nicht mit einem 2D-Array aufgerufen werden:

    int dings[5][5];
    foo(dings);
    

    Die Antwort ist: Der Typ von dings ist int[5][5] (Array von Arrays von 5 ints). Der/Die/Das "array-to-pointer decay" würde in einem Objekt vom Typ int(*)[5] resultieren (Zeiger auf (das erste) Array von 5 ints). Der Typ von x ist aber int** (Zeiger auf Zeiger auf int). Es passt also nicht zusammen.

    Was man auch nicht zu oft sagen kann: std::vector benutzen. Das Ding ist so schlau, dass es sogar weiß, wie groß es ist, kann die Größe dynamisch anpassen -- und das obwohl sizeof(std::vector<int>) konstant ist. 😉

    Gruß,
    SP



  • Das ist ein Bingo! 😉

    inglorious bastards geschaut?

    ok danke also bei dem vector bin ich in meinem Buch noch nicht angekommen und ich würde das ganze schon ein wenig geordnet angehen wollen.

    Mit dem Zerfallen kann man sich das so vorstellen, das der Typ immer um eins hin zur Adresse "degradiert wird" also aus:

    int[5][5] wird int* [5], aus int [5] wird int*

    nur wieso zerfällt die Stingtabelle, also die Parameter, die ich an main Übergebe zu char**?


  • Mod

    Max123 schrieb:

    int[5][5] wird int* [5], aus int [5] wird int*

    fast, Klammern nicht vergessen. Aus
    int[5][5] wird int(*)[5], eine Zeiger auf ein Array, nicht ein Array aus Zeigern - sonst könnte der Arrayzerfall ja weitergehen.

    nur wieso zerfällt die Stingtabelle, also die Parameter, die ich an main Übergebe zu char**?

    Das ist von vornherein ein Array aus Zeigern. Arrays zerfallen beim kleinsten Anzeichen von Gefahr zu Zeigern.



  • ok dann ist ja alles klar mich hat nur das in meinem Buch verwirrt:

    C-String-Tabellen sind [...] mehrdimensionale
    char-Arrays.

    Das hat mich annehmen lassen, dass mehrdimensionale Arrays und String Tabellen das selbe sind.

    Also zusammenfassend kann man sagen, Stringtabellen sind Arrays aus Zeigern und ein mehrdimensionales, "normales" Array ist ein Array aus Arrays.


  • Mod

    Max123 schrieb:

    ok dann ist ja alles klar mich hat nur das in meinem Buch verwirrt:

    C-String-Tabellen sind [...] mehrdimensionale
    char-Arrays.

    Das hat mich annehmen lassen, dass mehrdimensionale Arrays und String Tabellen das selbe sind.

    Dann ist die Aussage entweder ungenau oder falsch. Ein mehrdimensionales char Array ist sowas wie char[5][20], das wären 5 Zeichenkette mit Länge 19 (weil ein Zeichen bei cstrings für das Ende draufgeht). Es werden aber immer 20 chars pro Zeichenkette belegt, egal wie lang die Zeichenketten wirklich sind.

    Bei der Übergabe zur main hat man *char[], ein eindimensionales array von Zeigern auf andere chars. Dort wo diese Zeiger hinzeigen, liegen dann char Arrays mit genau der passenden Größe für die an main übergebenen Zeichenfolgen.



  • Man kann sich sogar darüber streiten, ob es eigentlich wirklich "mehrdimensionale Arrays" gibt, oder ob es nur Arrays von Arrays sind. :p

    In Pascal gibt es -- wenn ich mich richtig erinnere -- "echte" mehrdimensionale Arrays, bei denen die Indizierung nicht über [x][y], sondern [x,y] läuft.

    C++ erlaubt es einem aber, einen eigenen Typen so zu definieren, so dass er wie ein dynamisches mehrdimensionales Array benutzbar wird. ZB Boost.MultiArray.


Anmelden zum Antworten