[Mehrdimensionale Arrays]Frage zu Satz aus Lehrbuch



  • Erstmal danke an alle für die bisherigen Antworten.
    Was ein Array ist habe ich denke ich schon verstanden daran liegt es nicht:

    Definiere ich ein normales Array wird mir ein Pointer auf die Adresse des ersten Elements zurückgegeben.Diese Adresse kann ich mit dem Indexoperator/oder einem zweiten Pointer auf das Array z.B. um 1 inkrementieren um auf die nächste Adresse des Arrays zu stoßen.

    So wie ich Zweidimensionale Arrays in C++ verstanden habe:
    Sagen wir es gibt das Array int arr[3][4] es werden also 12 hinternanderfolgende Adressen für das Array reserviert (Der Speicherpool).
    Intern wird das zweidimensionale Array exakt wie ein ein ganz normales Array behandelt es sieht für den Programmierer nur anders aus.

    Echte Zweidimensionale Arrays:
    So wie ich es verstehe müsste ein echtes 2D Array so aussehen(In C++ gibt es sie nur nicht in dieser Form)
    const int a=3,b=4 ;
    Bei int arr[a][b] müsste man einen Pointer zurückgegeben bekommen welcher auf
    das erste Element von a zeigt.
    Das Array a würde aus einem Speicherpool von 3 Adressen bestehen.
    Jede dieser 3 Adressen verweist auf einen eigenen Speicherpool welcher jeweils 4 Typen vom Typ int aufnehmen kann.
    Bei einem echten Mehrdimensionalen Array würde also so wie ich es verstehe nicht ein zusammenhängender Speicherberreich für 12 Werte freigehalten werden.

    Zur Frage:
    Allerdings muss ich sagen der Satz "Abgerufen wird kein Element des Arrays,sondern das Array selbst." leuchtet mir immernoch nicht ein.
    Ein Array ist für mich ein Speicherpool und kein einzelner Typ wie soll ich einen gesamten Speicherpool abfragen?
    Das würde ja nur gehen indem ich z.B. die Adresse auf das erste Element des Speicherpools habe und diese dann inkrementiere dadurch würde ich aber wiederrum ein Element des Arrays ansprechen und laut dem Satz aus dem Buch ist das ja eben nicht der Fall.



  • VieleDimensionen schrieb:

    Erstmal danke an alle für die bisherigen Antworten.
    Was ein Array ist habe ich denke ich schon verstanden daran liegt es nicht

    Sicher? Ein Array ist eine Ansammlung von Elementen desselben Types die direkt aufeinanderfolgend im Speicher liegen.
    Wie du siehst kommt in dem Satz das Wort Pointer nicht vor. Ein Pointer hat mit einem Array nichts zu tun. Und ein Array hat mit einem Pointer nichts zu tun. Definierst du ein Array hast du ein Array mit N Elementen. Die Elemente des Arrays sprichst du mit [] und einem Index ( 0 bis N-1 ) an.
    Du kannst ein Array einem Pointer zuweisen. Dann geschieht array-to-pointer-decay. Das heißt es wird automatisch ein Zeiger generiert, der auf das erste Element des Arrays zeigt. Auf den Pointer kannst du Zeigerarithmetik anwenden. Und da *(Pointer + i) Pointer[i] gleichkommt, kannst du auf deinen Pointer [] und einen Index anwenden. Der Pointer wird dann um Index*Bytes verschoben, abhängig vom Datentyp.

    VieleDimensionen schrieb:

    So wie ich Zweidimensionale Arrays in C++ verstanden habe:

    Ein 2d Array ist ein Array von Arrays. Wie gesagt liegen alle Elemente eins Arrays direkt hintereinander im Speicher. Wenn ein Element des Arrays ein Array ist, liegen logischerweise alle Arrays direkt hintereinander im Speicher. Bei int arr[3][4] werden z.B. 3*4*int-Bytes Speicher direkt hintereinander reserviert (int hat oft 4 Bytes, aber nicht immer. Also 48 Bytes werden reserviert).
    Auch ein 2d Array hat nichts mit einem Pointer zu tun. Wenn du ein 2d Array einem Pointer zuweist, passiert wieder array-to-pointer-decay. Es wird also ein Zeiger generiert, der auf das erste Element des Arrays zeigt. Da das Array 2d ist, zeigt der Pointer also auf ein Array.

    VieleDimensionen schrieb:

    Allerdings muss ich sagen der Satz "Abgerufen wird kein Element des Arrays,sondern das Array selbst." leuchtet mir immernoch nicht ein.
    Ein Array ist für mich ein Speicherpool und kein einzelner Typ wie soll ich einen gesamten Speicherpool abfragen?

    Ach da versteckt sich der Übeltäter. Ein Array ist ein Typ. Genauso wie int ein Typ ist. Das musst du unbedingt in deinen Kopf einpflanzen. Ein int ist ein "Fundamentaler Datentyp". Ein Array ist ein "Zusammengesetzter Datentyp (compound type)".

    Mal ein paar Beispiele:

    int main()
    {
    	int ar[5] = {}; // Alle Elemente werden mit 0 belegt.
    	int* p  = ar; // array-to-pointer decay. ==> Für die Faulen.
    	int* p2 = &ar[0]; // Das ist das, was bei array-to-pointer-decay passiert. ==> Für die Pingeligen.
    
    	int ar_2d[3][4] = {};
    	int (*p3)[4] = ar_2d; // array-to-pointer-decay
    	int (*p4)[4] = &ar_2d[0]; // Ohne array-to-pointer-decay
    
    	// Es gibt noch einige andere Situationen, in denen array-to-pointer-decay stattfindet.
    	int array[5] = {};
    	*array; // Hier zum Beispiel. Du kannst ein Array nicht dereferenzieren, also muss vorher array-to-pointer-decay stattfinden.
    	*(&array[0]); // Ohne array-to-pointer-decay
    }
    


  • @out
    Laut dem was ich im buch gelesen habe sind Arrays und Pointer in C++ sehr eng miteinander verknüpft.
    Im Buch steht geschrieben,wenn ich int arr[5] definiere und den Namen arr in einem beliebigen Ausdruck z.B. arr[1]=3; verwende wird der Name automatisch in einen Zeiger auf das erste Element des Arrays umgewandelt und dann kann er z.B. mit dem Indexoperator in diesem Fall auf die nächste Adresse gesetzt werden.
    Also haben Zeiger und Arrays jawohl doch eine sehr enge Bindung in C++ ,denn man greift nicht direkt durch den Namen auf das Array zu ,sondern der Name des Arrays ist ein Pointer in welchem die Adresse des ersten Elements des Arrays zu finden ist.
    Dein letzter Satz ist mir einleuchtend und natürlich hast du Recht ein Vector ist ja auch ein Typ ,von daher muss ein Array das natürlich auch sein.

    Ich habe grade selbst mal getestet was mit dem Satz gemeint war anhand dieses Codes

    #include <iostream>
    
    int main() {
    	int a = 1;
    	int arr[3][4];
    	for (int i = 0; i < 2; ++i){
    		for (int in = 0; i < 3; ++i) {
    			arr[i][in] = a;
    			++a;
    		}
    	}
    	std::cout << &arr[2][0] <<std::endl;
    	std::cout << arr[2];
    
    	std::cin.get();
    
    	return 0;
    }
    

    Ich denke ich verstehe den Satz aus dem Buch nun.
    Es wird die selbe Adresse ausgegeben also greife ich mit arr[2] auf die erste Adresse der dritten Zeile des Arrays zu und nicht auf den Wert selbst der in diesem Array liegt.



  • Hatte noch nen dummen Fehler drinne sollte natürlich so aussehen:

    #include <iostream>
    
    int main() {
    	int a = 1;
    	int arr[3][4];
    	for (int i = 0; i <= 2; ++i){
    		for (int in = 0; in <= 3; ++in) {
    			arr[i][in] = a;
    			std::cout << arr[i][in]<<std::endl;
    			++a;
    
    		}
    	}
    	std::cout << &arr[2][0] <<std::endl;
    	std::cout << arr[2];
    
    	std::cin.get();
    
    	return 0;
    }
    

    Wenn ich nun in der Zeile arr[2] mit dem * Operator dereferenziere bekomme ich den Wert 9 (Dritte Zeile erstes Element).
    Ich finde daran sieht man doch sehr gut ,dass arr im Endeffekt nur ein Pointer auf die erste Adresse des Arrays von ist,und das Arrays und Pointer sehr eng miteinander verknüpft sind.



  • VieleDimensionen schrieb:

    @out
    Laut dem was ich im buch gelesen habe sind Arrays und Pointer in C++ sehr eng miteinander verknüpft.
    Im Buch steht geschrieben,wenn ich int arr[5] definiere und den Namen arr in einem beliebigen Ausdruck z.B. arr[1]=3; verwende wird der Name automatisch in einen Zeiger auf das erste Element des Arrays umgewandelt

    Das ist falsch. Das was in deinem Buch steht, ist falsch. Wie heißt dein Buch denn?

    VieleDimensionen schrieb:

    int main() {
    	int a = 1;
    	int arr[3][4];
    	for (int i = 0; i < 2; ++i){
    		for (int in = 0; i < 3; ++i) {
    			arr[i][in] = a;
    			++a;
    		}
    	}
    	std::cout << &arr[2][0] <<std::endl;
    	std::cout << arr[2];
    	 
    	std::cin.get();
    	
    	return 0;
    }
    

    Es wird die selbe Adresse ausgegeben also greife ich mit arr[2] auf die erste Adresse der dritten Zeile des Arrays zu und nicht auf den Wert selbst der in diesem Array liegt.

    Auch das ist falsch.
    1. Mit [] greifst du immer auf den Wert des Arrays zu, und nie auf eine Adresse eines Elements. Willst du auf eine Adresse zugreifen, musst du logischerweise den Adressoperator & nehmen.

    1. << ist eine Funktion. Nämlich operator<<(*/...*/) Übergibst du ein Array an eine Funktion, findet auch array-to-pointer-decay statt. Machst du nun std::cout << arr[2]; wird arr[2] an die Funktion operator<<(*/...*/) übergeben und du bekommst automatisch einen Zeiger auf das erste Element des Arrays. In der Funktion operator<<(*/...*/) wird dann einfach der Zeiger ausgegeben. Gibst du ein Zeigervariable aus, wird - wie bei jeder anderen Variable auch - der Inhalt der Variablen ausgeben. Der Inhalt einer Zeigervariablen ist die Adresse, auf die der Zeiger zeigt. Und diese Adresse ist jetzt halt die Adresse vom ersten Element des Arrays.

    Wie heißt jetzt nochmal dein Buch?:D



  • Ergänzung zu oben:
    Ein Array ist nie ein Zeiger auf irgendwas.
    Es gibt nur bestimmte Fälle, also Ausnahmen, wo ein Array in einen Zeiger auf das erste Element konvertiert werden muss. Da findet eine Konvertierung statt. Die müsste nicht stattfinden, wenn ein Array ein Zeiger wäre. Lässt sich auch leicht beweißen, dass ein Array kein Zeiger ist.

    int main() {
    	int array[5] = {1,2,3,4,5};
    	int nochmal_array[5] = {10,20,30,40,50};
    
    	array = nochmal_array; // Fehler
    
    	int* zeiger;
    	zeiger = nochmal_array; // Kein Fehler.
    }
    

    Wäre ein Array wie ein Zeiger, gäbe es keinen Fehler...



  • Also das verwirrt mich jetzt echt.
    Ich lerne mit dem C++ Primer das hier steht wörtlich so im Buch auf Seite 158:
    "Zeiger und Arrays sind in C++ eng miteinander verknüpft.
    Insbesondere wird der Name eines Arrays automatisch in einen Zeiger auf das erste Arrayelement umgewandelt,wenn wir ihn in einem Ausruck verwenden."
    Beispiel dazu aus dem Buch:

    int ia[] = {0,2,4,6,8};
    int *ip = ia;
    

    Und das Buch ist ja jetzt nicht von irgendeinem Deppen verfasst und bekommt überall gute Rückmeldungen.



  • VieleDimensionen schrieb:

    Also das verwirrt mich jetzt echt.
    Ich lerne mit dem C++ Primer das hier steht wörtlich so im Buch auf Seite 158:
    "Zeiger und Arrays sind in C++ eng miteinander verknüpft.
    Insbesondere wird der Name eines Arrays automatisch in einen Zeiger auf das erste Arrayelement umgewandelt,wenn wir ihn in einem Ausruck verwenden."

    Das ist im Wesentlichen richtig. Es stimmt für alle Ausdrücke außer für sizeof- und Adressausdrücke.

    Und das Buch ist ja jetzt nicht von irgendeinem Deppen verfasst und bekommt überall gute Rückmeldungen.

    Das hat nichts zu bedeuten.



  • 😃 Ja das Buch ist gut.

    Wie soll ich das jetzt erklären. Er meint nicht "immer wenn der Name des Arrays auftaucht", sondern er meint, wenn "DAS ARRAY" an sich auftaucht. Also

    int ia[] = {0,2,4,6,8};
    int *ip = ia; // ia => DAS ARRAY an sich.
    
    int ia[] = {0,2,4,6,8};
    int varialbe = ia[0]; // Hier ist es aber ia[N], und NICHT das Array an sich.
    

    Verstehst du nun, worauf es hinausläuft. Also ohne Indexoperator ist das Array an sich.



  • out schrieb:

    😃 Ja das Buch ist gut.

    Wie soll ich das jetzt erklären. Er meint nicht "immer wenn der Name des Arrays auftaucht", sondern er meint, wenn "DAS ARRAY" an sich auftaucht. Also

    int ia[] = {0,2,4,6,8};
    int *ip = ia; // ia => DAS ARRAY an sich.
    
    int ia[] = {0,2,4,6,8};
    int varialbe = ia[0]; // Hier ist es aber ia[N], und NICHT das Array an sich.
    

    Verstehst du nun, worauf es hinausläuft. Also ohne Indexoperator ist das Array an sich.

    Achso ja jetzt habe ich es auch verstanden :D.
    Der Name allein ohne Index wird zum Zeiger auf das erste Element umgewandelt und der Name mit Index wird einfach direkt angesprochen.
    Ich schätze mal es wird der Übersetzung des Buches ins Deutsche geschuldet sein,aber ich hatte einfach keinen Nerv so einen Wälzer komplett in Englisch zu lesen.
    Nochmals vielen Dank an euch für die Hilfe. 👍



  • out schrieb:

    int ia[] = {0,2,4,6,8};
    int varialbe = ia[0]; // Hier ist es aber ia[N], und NICHT das Array an sich.
    

    Verstehst du nun, worauf es hinausläuft. Also ohne Indexoperator ist das Array an sich.

    Falls du damit sagen willst, dass das Array hier nicht in einen Zeiger umgewandelt wird, liegst du falsch. Ergebnis:

    Achso ja jetzt habe ich es auch verstanden :D.

    Ja, toll 👎



  • Bashar schrieb:

    out schrieb:

    int ia[] = {0,2,4,6,8};
    int varialbe = ia[0]; // Hier ist es aber ia[N], und NICHT das Array an sich.
    

    Verstehst du nun, worauf es hinausläuft. Also ohne Indexoperator ist das Array an sich.

    Falls du damit sagen willst, dass das Array hier nicht in einen Zeiger umgewandelt wird, liegst du falsch. Ergebnis:

    Achso ja jetzt habe ich es auch verstanden :D.

    Ja, toll 👎

    Oh nein bitte nicht 😃 .
    Und wer hat jetzt Recht?



  • Bashar schrieb:

    out schrieb:

    int ia[] = {0,2,4,6,8};
    int varialbe = ia[0]; // Hier ist es aber ia[N], und NICHT das Array an sich.
    

    Verstehst du nun, worauf es hinausläuft. Also ohne Indexoperator ist das Array an sich.

    Falls du damit sagen willst, dass das Array hier nicht in einen Zeiger umgewandelt wird, liegst du falsch.

    Das hör ich jetzt zum ersten Mal. Kann das jemand bestätigen 😃 ?



  • Du könntest in einem C++-Buch deines Vertrauens oder im Standard nachlesen, wie der []-Operator definiert ist.



  • So ich habe nochmal nachgeforscht auf der MSDN Seite wird es auch so erklärt:

    "Usually, the value represented by postfix-expression is a pointer value, such as an array identifier, and expression is an integral value (including enumerated types). However, all that is required syntactically is that one of the expressions be of pointer type and the other be of integral type. Thus the integral value could be in the postfix-expression position and the pointer value could be in the brackets in the expression or subscript position. Consider the following code fragment:"

    int nArray[5] = { 0, 1, 2, 3, 4 };
       cout << nArray[2] << endl;            // prints "2"
       cout << 2[nArray] << endl;            // prints "2"
    

    Und hier die fortsetzung:
    "In the preceding example, the expression nArray[2] is identical to 2[nArray]. The reason is that the result of a subscript expression e1[ e2 ] is given by:"

    *( (e2) + (e1) )
    

    Das Ergebniss wird also mit dem vorangestellten * dereferenziert was ja nochmal deutlich macht,dass es sich hier im einen Pointer handelt .



  • Bashar schrieb:

    Du könntest in einem C++-Buch deines Vertrauens oder im Standard nachlesen, wie der []-Operator definiert ist.

    Ok, muss ich mal gugen. Könnte schwören das trifft auf [] nicht zu.

    Ok, dann muss man also sagen, dass es Ausnahmen gibt, bei denen array-to-pointer-decay nicht passiert, z.B. bei call-by-reference. Hab ich in diesem Thread auch was gelernt :).



  • VieleDimensionen schrieb:

    Das Ergebniss wird also mit dem vorangestellten * dereferenziert was ja nochmal deutlich macht,dass es sich hier im einen Pointer handelt .

    Vorsicht mit solchen Interpretationen. Das Array ist selbst kein Pointer, es wird in einen Pointer umwandelt. Den Unterschied siehst du dann, wenn diese Umwandlung mal nicht passiert, z.B. bei sizeof(array) und bei &array. Ansonsten führt diese Umwandlung dazu, dass sich ein Array weitestgehend wie ein Pointer anfühlt, daher auch diese relativ ungenaue Beschreibung in der MSDN.



  • Bashar schrieb:

    VieleDimensionen schrieb:

    Das Ergebniss wird also mit dem vorangestellten * dereferenziert was ja nochmal deutlich macht,dass es sich hier im einen Pointer handelt .

    Vorsicht mit solchen Interpretationen. Das Array ist selbst kein Pointer, es wird in einen Pointer umwandelt. Den Unterschied siehst du dann, wenn diese Umwandlung mal nicht passiert, z.B. bei sizeof(array) und bei &array. Ansonsten führt diese Umwandlung dazu, dass sich ein Array weitestgehend wie ein Pointer anfühlt, daher auch diese relativ ungenaue Beschreibung in der MSDN.

    Kann ich es dann so verstehen?:
    Das Array selbst ist einfach ein Typ welcher aus anderen Typen zusammengesetzt wird.

    Um aber mit den einzelnen Werten der Elementen eines Arrays zu arbeiten wird ein Pointer erzeugt welcher auf die Adresse des ersten Elements zeigt.Mithilfe der im Pointer enthaltenden Start Adresse ist es dann möglich die anderen Adressen der im Array enthaltenden Elemente zu berechnen.



  • Ja, genau so ist es.


  • Mod

    Das Array selbst ist einfach ein Typ welcher aus anderen Typen zusammengesetzt wird.

    Abgesehen von der Tatsache dass es nur ein Typ ist und nicht mehrere ist das korrekt. Arrays sind neben Klassen, Funktionen, Zeigern, Referenzen und Enumerationen auch sog. compound types - zusammengesetzte Typen.

    Ok, muss ich mal gugen. Könnte schwören das trifft auf [] nicht zu.

    Doch.

    One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type.
    The result is of type “ T .” The type “ T ” shall be a completely-defined object type. **The expression E1[E2] is identical (by definition) to *((E1)+(E2)) **[...].

    Im Ausdruck (E1)+(E2) zerfällt, wenn E1 oder E2 ein Arrayobjekt ist, dieses Arrayobjekt zu einem Zeiger. Auf diesen Zeiger wird dann der Index addiert. Natürlich aber ist das Arrayobjekt zu keinem Zeitpunkt ein Zeiger - die Differenzierung im Zitat macht das nochmal deutlich.


Anmelden zum Antworten