Zeiger auf Arrays in C

8

Ich habe gerade dieses Code-Snippet Q4 hier gesehen und mich gefragt, ob ich das richtig verstanden habe.

%Vor%

Hier ist meine Erklärung:

int a[5] = { 1, 2, 3, 4, 5 }; = & gt; a zeigt auf das erste Element des Arrays. Mit anderen Worten: a enthält die Adresse des ersten Elements des Arrays.

int *ptr = (int*)(&a + 1); = & gt; Hier wird &a ein Doppelzeiger sein und auf das ganze Array zeigen. Ich visualisiere es so: int b[1][5] = {1, 2, 3, 4, 5}; , hier b zeigt auf eine Zeile eines 2D-Arrays. &a + 1 sollte auf das nächste Array von Ganzzahlen im Speicher zeigen (nicht vorhanden) [Art von% b + 1 zeigt auf die zweite (nicht vorhandene) Zeile eines 2D-Arrays mit 1 Zeile]. Wir werfen es als int * , also sollte dies wahrscheinlich auf das erste Element des nächsten Arrays (nicht vorhanden) im Speicher zeigen.

*(a + 1) = & gt; Das ist einfach. Es zeigt nur auf das zweite Element des Arrays.

*(ptr - 1) = & gt; Dieser ist knifflig, und meine Erklärung ist wahrscheinlich fehlerhaft für diesen. Da ptr ein int * ist, sollte dies auf int vor dem Wert von ptr verweisen. ptr zeigt auf das nicht vorhandene zweite Array im Speicher. Daher sollte ptr - 1 wahrscheinlich auf das letzte Element des ersten Arrays zeigen ( a[4] ).

    
Aneesh Dogra 03.01.2014, 07:12
quelle

3 Antworten

6
%Vor%

Nein. Es ist ein Zeiger auf ein Array. In diesem Beispiel int (*)[5] . Siehe C-Zeiger auf Array / Array der Zeiger-Disambiguierung

Wenn Sie also den Zeiger auf ein Array erhöhen, wird das Array durchkreuzt und auf eine nicht vorhandene Stelle gezeigt.

In diesem Beispiel wird es einem Ganzzahlzeiger zugewiesen. Wenn also der Zeiger dekrementiert wird, zeigt er auf die vorherige Größe von (int) Bytes. also 5 ist gedruckt.

    
Jeyaram 03.01.2014, 07:36
quelle
1

Laut Ihrer Erklärung verstehen Sie den Array-Zeiger korrekt. Mit der Anweisung

%Vor%

Sie zeigen auf die nächste Adresse der Adresse, die vom ganzen Array a[] belegt ist, so dass Sie mit ptr auf das Array-Element zugreifen können, indem Sie die Adresse von ptr.

dekrementieren     
Jayesh Bhoi 03.01.2014 07:30
quelle
1

Ihre Aussage ist im Wesentlichen richtig und Sie verstehen sie wahrscheinlich besser als die meisten Profis. Aber da Sie eine Kritik suchen, hier ist die lange Antwort. Arrays und Zeiger in C sind verschiedene Typen, dies ist eine der subtilsten Details in C. Ich erinnere mich an einen meiner Lieblingsprofessoren, der einmal sagte, dass die Leute, die die Sprache gemacht haben, bereuten, dies so subtil und oft verwirrend zu machen.

In vielen Fällen ist es ein Array eines Typs, und ein Zeiger auf einen Typ kann auf die gleiche Weise behandelt werden. Sie haben beide einen Wert, der ihrer Adresse entspricht, aber sie sind wirklich unterschiedliche Typen.

Wenn Sie die Adresse eines Arrays &a verwenden, haben Sie einen Zeiger auf ein Array . Wenn Sie (a + 1) sagen, haben Sie einen Zeiger auf ein int , wenn Sie einfach a sagen, haben Sie ein Array (kein Zeiger). a[1] entspricht genau der Eingabe von *(a + 1) , tatsächlich könnten Sie 1[a] eingeben und es wäre genau dasselbe wie die vorherigen beiden. Wenn Sie ein Array an eine Funktion übergeben, übergeben Sie nicht wirklich ein Array. Sie übergeben einen Zeiger.% Co_de% und void Fn(int b[]) sind beide genau die gleiche Funktionssignatur, wenn Sie in beiden Fällen void Fn(int *b) innerhalb der Funktion verwenden Sie erhalten die Größe eines Zeigers.

Die Zeigerarithmetik ist schwierig, sie wird immer um die Größe des Objekts verschoben, auf das sie in Bytes zeigt. Immer wenn Sie die Adresse des Operators verwenden, erhalten Sie einen Zeiger auf den Typ, auf den Sie ihn angewendet haben.

Also, was in deinem obigen Beispiel passiert:

  • sizeof b ist ein Zeiger auf ein Array. Wenn Sie also ein Objekt hinzufügen, wird es um die Größe dieses Arrays &a .
  • versetzt
  • Wenn Sie in (5 * sizeof(int)) umwandeln, behält der Cast den Wert des Zeigers bei, aber jetzt ist sein Typ Zeiger auf int . Sie speichern ihn dann in int* , eine Variable vom Typ < em> Zeiger auf int .
  • ptr ist ein Array, kein Zeiger. Wenn Sie also a angeben, wenden Sie den Additionsoperator auf ein Array und nicht auf einen Zeiger an. und dies ergibt einen Zeiger auf eins nach dem ersten Element des im Array gespeicherten Typs a + 1 . Wenn Sie es mit int auflösen, erhalten Sie das int , auf das gezeigt wird.
  • * ist ein Zeiger auf int und zeigt auf eins nach dem Ende des Arrays. (Es ist legal übrigens, einen über das Ende eines Arrays hinaus zu weisen, es ist einfach nicht erlaubt, diesen Zeiger zu dereferenzieren). Wenn Sie 1 davon abziehen, erhalten Sie einen Zeiger auf ein int, das das letzte im Array ist. was du dereferenzieren kannst. (Ihr Erklären der Visualisierung von ptr ist etwas, was ich noch nie zuvor gehört habe, und obwohl ich nicht ehrlich sagen kann, ob das technisch korrekt ist, werde ich sagen, dass dies so funktioniert und ich denke, dass dies eine großartige Möglichkeit ist, darüber nachzudenken Es wird wahrscheinlich von nun an in meinem Hinterkopf sein.)

Typen werden in C und auch in C ++ sehr schwierig. Das Beste kommt erst noch.

    
Apriori 03.01.2014 08:23
quelle

Tags und Links