Was ist der Unterschied zwischen den folgenden Erklärungen?
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
Was ist die allgemeine Regel für das Verständnis komplexerer Erklärungen?
Was ist der Unterschied zwischen den folgenden Erklärungen?
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
Was ist die allgemeine Regel für das Verständnis komplexerer Erklärungen?
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 lautet Vorrang des Operators . Es kann sogar noch viel komplexer werden, wenn Funktionszeiger ins Spiel kommen.
Verwenden Sie die cdecl Programm, 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 )
Ich weiß nicht, ob es einen offiziellen Namen hat, aber ich nenne es das Rechts-Links-Dingsbums(TM).
Beginnen Sie bei der Variablen, gehen Sie dann nach rechts, nach links, nach rechts und so weiter.
int* arr1[8];
arr1
ist ein Array mit 8 Zeigern auf Ganzzahlen.
int (*arr2)[8];
arr2
ist ein Zeiger (die Klammer blockiert die rechte linke Seite) auf ein Array von 8 Ganzzahlen.
int *(arr3[8]);
arr3
ist ein Array mit 8 Zeigern auf Ganzzahlen.
Dies sollte Ihnen bei komplexen Deklarationen helfen.
Die Antwort auf die beiden letzten Fragen lässt sich auch aus der goldenen Regel in C ableiten:
Die Erklärung erfolgt nach der Verwendung.
int (*arr2)[8];
Was passiert, wenn Sie eine Dereferenzierung arr2
? Sie erhalten ein Array mit 8 Ganzzahlen.
int *(arr3[8]);
Was passiert, wenn Sie ein Element aus arr3
? Sie erhalten einen Zeiger auf eine Ganzzahl.
Dies ist auch beim Umgang mit Zeigern auf Funktionen hilfreich. Um das Beispiel von sigjuice zu nehmen:
float *(*x)(void )
Was passiert, wenn Sie eine Dereferenzierung x
? Sie erhalten eine Funktion, die Sie ohne Argumente aufrufen können. Was passiert, wenn Sie sie aufrufen? Sie gibt einen Zeiger auf ein float
.
Der Vorrang von Operatoren ist jedoch immer schwierig. Allerdings kann die Verwendung von Klammern auch verwirrend sein, weil die Erklärung der Verwendung folgt. Zumindest für mich, intuitiv arr2
sieht aus wie ein Array von 8 Zeigern auf ints, aber es ist eigentlich andersherum. Daran muss man sich erst einmal gewöhnen. Grund genug, diese Deklarationen immer mit einem Kommentar zu versehen, wenn Sie mich fragen :)
edit: 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;
}
出力します。
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, so dass der Compiler dies wegoptimieren kann. Dies unterscheidet sich von dem, was Sie anfangs vielleicht verwenden möchten: const int (*border)[3]
: Diese deklariert border als Zeiger auf ein Array von 3 Ganzzahlen, das seinen Wert nicht ändert, solange die Variable existiert. Dieser Zeiger kann jedoch jederzeit auf ein anderes solches Array zeigen. Wir möchten, dass sich das Argument so verhält (denn diese Funktion ändert keine dieser Ganzzahlen). Die Deklaration folgt der Verwendung.
(p.s.: Sie können dieses Beispiel gerne verbessern!)
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.