übergeben - pointer c




C Zeiger auf Array/Array von Zeigern Disambiguierung (8)

Was ist der Unterschied zwischen den folgenden Deklarationen:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

Was ist die allgemeine Regel, um komplexere Deklarationen zu verstehen?


Als Faustregel gilt, dass rechts unäre Operatoren (wie [] , () usw.) Vorrang vor den linken haben. Also, int *(*ptr)()[]; wäre ein Zeiger, der auf eine Funktion verweist, die ein Array von Zeigern an int zurückgibt (die richtigen Operatoren sobald wie möglich aus der Klammer holen)


Die Antwort für die letzten beiden kann auch von der goldenen Regel in C abgeleitet werden:

Erklärung folgt Verwendung.

int (*arr2)[8];

Was passiert, wenn Sie arr2 dereferenzieren? Sie erhalten ein Array von 8 ganzen Zahlen.

int *(arr3[8]);

Was passiert, wenn du ein Element von arr3 nimmst? Sie erhalten einen Zeiger auf eine ganze Zahl.

Dies hilft auch beim Umgang mit Zeigern auf Funktionen. Um das Beispiel von sigjuice zu nehmen:

float *(*x)(void )

Was passiert, wenn Sie x dereferenzieren? Sie erhalten eine Funktion, die Sie ohne Argumente aufrufen können. Was passiert, wenn Sie es anrufen? Es wird einen Zeiger auf einen Float zurückgegeben.

Die Vorrangstellung des Betreibers ist jedoch immer schwierig. Die Verwendung von Klammern kann jedoch auch verwirrend sein, da die Deklaration der Verwendung folgt. Zumindest für mich sieht arr2 intuitiv aus wie ein Array von 8 Zeigern auf Ints, aber es ist eigentlich umgekehrt. Es braucht nur etwas gewöhnungsbedürftig. Grund genug, diesen Erklärungen immer einen Kommentar hinzuzufügen, wenn du mich fragst :)

Bearbeiten: Beispiel

Übrigens bin ich gerade über die folgende Situation gestolpert: eine Funktion, die eine statische Matrix hat und die Zeigerarithmetik verwendet, um zu sehen, ob der Zeilenzeiger außerhalb der Grenzen liegt. Beispiel:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i < 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}

Ausgabe:

0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]

Beachten Sie, dass sich der Wert von border nie ändert, sodass der Compiler diesen Wert optimieren kann. Dies ist anders als das, was Sie ursprünglich verwenden möchten: const int (*border)[3] : Das deklariert den Rahmen als Zeiger auf ein Array von 3 Ganzzahlen, die den Wert nicht ändern, solange die Variable existiert. Dieser Zeiger kann jedoch zu irgendeinem Zeitpunkt auf irgendein anderes solches Feld gerichtet sein. Wir wollen stattdessen dieses Verhalten für das Argument (weil diese Funktion keine dieser ganzen Zahlen ändert). Erklärung folgt Verwendung.

(PS: Fühlen Sie sich frei, diese Probe zu verbessern!)


Ich denke, wir können die einfache Regel verwenden ..

example int * (*ptr)()[];
start from ptr 

" ptr ist ein Zeiger auf" gehe nach rechts ..its ")" gehe nun nach links ein a "(" komm raus geh nach rechts "()" so "zu einer Funktion, die keine Argumente" gehe nach links "und gibt einen Zeiger zurück" gehe nach rechts "zu einem Array" gehe nach links "von ganzen Zahlen"


Ich schätze, die zweite Erklärung ist für viele verwirrend. Hier ist eine einfache Art, es zu verstehen.

Lets haben ein Array von ganzen Zahlen, dh int B[8] .

Lassen Sie uns auch eine Variable A haben, die auf B zeigt. Nun ist der Wert bei A B, dh (*A) == B Daher zeigt A auf ein Array von ganzen Zahlen. In Ihrer Frage ist arr ähnlich wie A.

Ähnlich ist in int* (*C) [8] C ein Zeiger auf ein Array von Zeigern auf Integer.


Im Zeiger auf eine Ganzzahl, wenn der Zeiger inkrementiert wird, geht er als nächste Ganzzahl.

Im Zeigerbereich, wenn der Zeiger inkrementiert wird, springt er zum nächsten Feld


Verwenden Sie das Programm cdecl , wie von K & R vorgeschlagen.

$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>

Es funktioniert auch andersherum.

cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers

Der dritte ist der gleiche wie der erste.

Die allgemeine Regel ist der unixwiz.net/techtips/reading-cdecl.html . Es kann sogar viel komplexer werden, wenn Funktionszeiger ins Bild kommen.


typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];




variable-declaration