[C++] Vektoren und deren Übergabe an Funktionen



  • Hi!

    ich habe einige relativ allgemeine Fragen zu Vektoren und deren Nutzung in C++. Das Thema kommt zwar relativ oft auf, aber ich habe bis heute keine wirkliche Lösung zu meinen Fragen gefunden.

    1. Eindimensionaler Vektor
    Gehe ich richtig in der Annahme, dass ein eindimensionaler Vektor im Arbeitsspeicher nur ein zusammenhängender Block der Werte ist. Beispiel

    int vektor[3]={1,2,3};
    

    sollte im Speicher

    |1|2|3|

    sein. Es wird somit keine Adresse im Arbeitsspeicher gespeichert, also kein Zeiger auf das erste Element angelegt. Der Name vektor wird vom Compiler aber in eine Adresse (evtl. inclusive Offset übersetzt).

    Soweit so richtig ?

    2. Aufruf eine Eindimensionalen Vektors

    void funktion(int *ptr, int elemente)
    {
        ptr[2]=... //und soweiter und sofort
    }
    

    Beim Aufruf der Funktion wird einfach die Adresse übergeben. Die Adresse wird in dem Zeiger ptr gespeichert. Anschließend wird zur Adresse wegen ptr[2] einfach 8 byte für 2 int dazugezählt. Somit gibt es jetzt im Unterschied zu oben im Speicher einen Zeiger.

    Richtig?

    3. Mehrdimensionales Array

    vektor[2][3]= { {1,2,3}, {4,5,6} };
    

    Bei mehrdimensionalen Vektoren existiert zum eindimensionalen Vektor aus 1. auser den Unterschiedlichen Zahlen im Arbeitsspeicher kein Unterschied.
    Also:
    |1|2|3|4|5|6|

    Richtig?

    4. Übergabe von 2-dimensionalem Vektor

    void funktion2(int array[][3])
    {
        array[1][1]=... /und soweiter und sofort
    }
    

    Meine Frage ist nun aber, wo im Gegensatz zu 2. der Zeiger geblieben ist. Beim Aufruf wird wieder die Adresse mit dem ersten Element übergeben. Aber warum habe ich im Gegensatz zu 1. jetzt nicht wieder einen Zeiger, wie z.B.

    void funktion2(int *ptr)
    {
        ptr[1][1]=... /und soweiter und sofort
    }
    

    oder sogar einen Array von Zeigern wie z.B.

    void funktion2(int *ptr[3])
    {
        //jeder Zeiger zeigt auf eine Zeile oder Spalte
    }
    

    Was passiert denn nun mit der Adresse, die am Funktionsaufruf übergeben wird? Wird die in einem Zeiger im Speicher gespeichert? Und wie viele Zeiger gibt es bei 2-dimensionalen Arrays? 1 oder 2 oder 4?

    Ich hoffe ihr könnt ein bischen Licht ins Dunkel bringen.



  • Edit: Ach, er meinte nichts mit std::vector . Das hat mich verwirrt.



  • anon99 schrieb:

    1. Eindimensionaler Vektor
    Gehe ich richtig in der Annahme, dass ein eindimensionaler Vektor im Arbeitsspeicher nur ein zusammenhängender Block der Werte ist. Beispiel

    int vektor[3]={1,2,3};
    

    sollte im Speicher

    |1|2|3|

    Richtig.

    anon99 schrieb:

    2. Aufruf eine Eindimensionalen Vektors

    void funktion(int *ptr, int elemente)
    {
        ptr[2]=... //und soweiter und sofort
    }
    

    Beim Aufruf der Funktion wird einfach die Adresse übergeben. Die Adresse wird in dem Zeiger ptr gespeichert. Anschließend wird zur Adresse wegen ptr[2] einfach 8 byte für 2 int dazugezählt.

    Richtig. Bei der Übergabe an eine Funktion zerfällt das Array in einen Zeiger auf das erste Element des Arrays. Jain. Ob es 8 Bytes sind, ist systemabhängig, darauf kannst du dich nicht verlassen. Es gibt bestimmt auch Systeme, wo es 2*2Bytes sind.

    anon99 schrieb:

    3. Mehrdimensionales Array

    vektor[2][3]= { {1,2,3}, {4,5,6} };
    

    Bei mehrdimensionalen Vektoren existiert zum eindimensionalen Vektor aus 1. auser den Unterschiedlichen Zahlen im Arbeitsspeicher kein Unterschied.
    Also:
    |1|2|3|4|5|6|

    Richtig.

    anon99 schrieb:

    4. Übergabe von 2-dimensionalem Vektor

    void funktion2(int array[][3])
    {
        array[1][1]=... /und soweiter und sofort
    }
    

    Meine Frage ist nun aber, wo im Gegensatz zu 2. der Zeiger geblieben ist. Beim Aufruf wird wieder die Adresse mit dem ersten Element übergeben.

    Richtig. Auch hier hast du ein array-to-pointer decay. Deine Schreibweise ist nur unglücklich gewählt:

    void funktion2(int (*p)[3])
    {
        p[1][1];
    }
    

    p is a pointer to an array of 3 ints.

    anon99 schrieb:

    Aber warum habe ich im Gegensatz zu 1. jetzt nicht wieder einen Zeiger, wie z.B.

    void funktion2(int *ptr)
    {
        ptr[1][1]=... /und soweiter und sofort
    }
    

    oder sogar einen Array von Zeigern wie z.B.

    void funktion2(int *ptr[3])
    {
        //jeder Zeiger zeigt auf eine Zeile oder Spalte
    }
    

    Was passiert denn nun mit der Adresse, die am Funktionsaufruf übergeben wird? Wird die in einem Zeiger im Speicher gespeichert? Und wie viele Zeiger gibt es bei 2-dimensionalen Arrays? 1 oder 2 oder 4?

    Du bekommst bei der Übergabe eines Arrays eine Funktion immer einen Zeiger auf das erste Element des Arrays:

    void funktion2(int (*p)[3][4][5][6])
    {
        p[1][2][3][4][5];
    }
    

    p is a pointer to an array of 3 arrays of 4 arrays of 5 arrays of 6 ints.



  • danke, die C++ Schreibweise mit array[][3] hat mich ein bisschen verwirrt. Ich habe nicht kapiert, dass das eine Schreibweise für Zeiger auf einen Array ist.



  • anon99 schrieb:

    danke, die C++ Schreibweise mit array[][3] hat mich ein bisschen verwirrt. Ich habe nicht kapiert, dass das eine Schreibweise für Zeiger auf einen Array ist.

    Nein, das ist es auch nicht! Wenn du

    int array[][3] = {...
    

    schreibst, lässt du die Größe der ersten Dimension deduzieren.



  • anon99 schrieb:

    danke, die C++ Schreibweise mit array[][3] hat mich ein bisschen verwirrt. Ich habe nicht kapiert, dass das eine Schreibweise für Zeiger auf einen Array ist.

    Aber Vorsicht. Das ist nur bei der Übergabe an eine Funktion so. Du kannst nicht einfach überall [][] durch (*)[] ersetzen, weil ein Array kein zeiger ist und umgekehrt.



  • Sone schrieb:

    Nein, das ist es auch nicht! Wenn du

    int array[][3] = {...
    

    schreibst, lässt du die Größe der ersten Dimension deduzieren.

    was um alles in der Welt muss ich unter deduzieren verstehen?



  • anon99 schrieb:

    Sone schrieb:

    Nein, das ist es auch nicht! Wenn du

    int array[][3] = {...
    

    schreibst, lässt du die Größe der ersten Dimension deduzieren.

    was um alles in der Welt muss ich unter deduzieren verstehen?

    Sone wollte dir damit sagen, dass du die die Größe der ersten Dimension hier nicht angeben musst, da sie der Compiler selbst berechnen kann, also überlassen wir es doch dem Compiler.



  • out schrieb:

    anon99 schrieb:

    Sone schrieb:

    Nein, das ist es auch nicht! Wenn du

    int array[][3] = {...
    

    schreibst, lässt du die Größe der ersten Dimension deduzieren.

    was um alles in der Welt muss ich unter deduzieren verstehen?

    Sone wollte dir damit sagen, dass du die die Größe der ersten Dimension hier nicht angeben musst, da sie der Compiler selbst berechnen kann, also überlassen wir es doch dem Compiler.

    Deduktion ist einfach "Ableitung". Man kann also logisch erkennen, wie groß die erste Dimension ist.

    Faustregel: Mach nichts, was der Compiler für dich erledigen kann!



  • Man könnte auch "herleiten" sagen. Oder "folgern".
    Was im Zusammenhang mit Sprachen die Objektorientierung mit Vererbung unterstützen weniger verwirrend wäre als "ableiten".


Anmelden zum Antworten