Die Antwort für die letzten beiden kann auch von der goldenen Regel in C abgezogen werden:
Erklärung folgt Verwendung.
int (*arr2)[8];
Was passiert, wenn Sie dereferenzieren arr2
? Sie erhalten ein Array von 8 Ganzzahlen.
int *(arr3[8]);
Was passiert, wenn Sie ein Element entnehmen arr3
? Sie erhalten einen Zeiger auf eine Ganzzahl.
Dies hilft auch beim Umgang mit Zeigern auf Funktionen. Um das Beispiel von Sigjuice zu nehmen:
float *(*x)(void )
Was passiert, wenn Sie dereferenzieren x
? Sie erhalten eine Funktion, die Sie ohne Argumente aufrufen können. Was passiert, wenn Sie es nennen? Es wird ein Zeiger auf a zurückgegeben float
.
Die Priorität des Bedieners ist jedoch immer schwierig. Die Verwendung von Klammern kann jedoch auch verwirrend sein, da die Deklaration auf die Verwendung folgt. Zumindest arr2
sieht es für mich intuitiv aus wie ein Array von 8 Zeigern auf Ints, aber es ist tatsächlich umgekehrt. Es ist nur gewöhnungsbedürftig. Grund genug, diesen Erklärungen immer einen Kommentar hinzuzufügen, wenn Sie mich fragen :)
bearbeiten: Beispiel
Übrigens bin ich gerade auf die folgende Situation gestoßen: Eine Funktion mit einer statischen Matrix, die Zeigerarithmetik verwendet, um festzustellen, 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 dies optimieren kann. Dies unterscheidet sich von dem, was Sie ursprünglich verwenden möchten const int (*border)[3]
:: Das deklariert border als Zeiger auf ein Array von 3 Ganzzahlen, die den Wert nicht ändern, solange die Variable vorhanden ist. Dieser Zeiger kann jedoch jederzeit auf ein anderes solches Array gerichtet sein. Wir wollen stattdessen diese Art von Verhalten für das Argument (weil diese Funktion keine dieser ganzen Zahlen ändert). Erklärung folgt Verwendung.
(ps: zögern Sie nicht, dieses Beispiel zu verbessern!)