web-dev-qa-db-de.com

Überschüssige Elemente des Skalar-Initialisierers für den Zeiger auf ein Array von Ints

Ich arbeite an einer Übung in K & R (Beispiel 5–9) und habe versucht, das 2D-Array des ursprünglichen Programms zu konvertieren

static char daytab[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

in die Verwendung von Zeigern auf ein Array von 13 Ints wie

static char (*daytab)[13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

Der Compiler gibt jedochwarning aus: überschüssige Elemente im Skalar-Initialisierer.

Googeln hat nicht geholfen und sogar K & R schreibt, wenn das Array an eine Funktion übergeben wird.

myFunction(int daytab[2][13]) {...}

ist das gleiche wie

myFunction(int (*daytab)[13]) {...}
25
adelbertc

Die beiden sind nur teilweise gleichwertig. Der Unterschied ist:

static char daytab[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

deklariert ein zweidimensionales Array, das Platz für das Array enthält und sicherstellen, dass daytab auf diesen Speicher verweist. Jedoch:

static char (*daytab)[13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

... deklariert nur einen Zeiger. Sie versuchen also, einen Zeiger mit einem Array-Initialisierer zu initialisieren, der nicht wie erwartet funktioniert. Es gibt kein Array; Es gibt keinen Speicher für ein Array. Stattdessen wird die erste Zahl in Ihrem Initialisierer dem Zeiger daytab zugewiesen, und der Compiler gibt eine Warnung aus, die Sie darauf hinweist, dass Sie viele zusätzliche Werte angegeben haben, die gerade verworfen werden. Da die erste Zahl in Ihrem Initialisierer 0 ist, setzen Sie daytab nur NULL auf eine ziemlich ausführliche Art und Weise.

Wenn Sie diese Art der Initialisierung durchführen möchten, verwenden Sie die erste Version - sie zerfällt auf den Zeigertyp, den Sie in der zweiten Version explizit deklarieren, sodass Sie sie auf dieselbe Weise verwenden können. Die zweite Version mit dem Arrayzeiger wird benötigt, wenn Sie das Array dynamisch zuweisen oder einen Verweis auf ein anderes bereits vorhandenes Array erhalten möchten.

So kannst du das machen:

static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;

ptr = arr;

... und dann ptr und arr austauschbar verwenden. Oder dieses:

static char (*ptr)[3] = NULL;

ptr = malloc(2 * sizeof(*ptr));

... um ein dynamisch zugewiesenes 2-dimensionales Array zu erhalten (kein Array von Zeigern auf 1D-Arrays, sondern ein reales 2D-Array). Natürlich wird es in diesem Fall nicht initialisiert.

Die "Äquivalenz" der beiden Variationen bedeutet nur, dass das 2D-Array, wenn es zu einem Zeiger auf sein erstes Element zerfällt, zu dem in der zweiten Variation deklarierten Zeigertyp zerfällt. Sobald die Zeigerversion tatsächlich auf ein Array gerichtet ist, sind die beiden gleichwertig. Bei der 2D-Array-Version wird jedoch Speicher für das Array eingerichtet, bei der die Zeigerdeklaration nicht ... und dem Zeiger kann ein neuer Wert zugewiesen werden (auf ein anderes Array gerichtet), bei dem die 2D-Array-Variable nicht möglich ist.

In C99 ist dies jedoch möglich (falls nicht static):

char (*daytab)[13] = (char [][13]){
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
27
Dmitri

@Dmitri hat es gut erklärt, aber ich wollte das hinzufügen 

static char (*daytab)[13] = { ... };

ist one - Zeiger auf ein Array von 13 char-Elementen. Der Compiler gibt die Warnung aus, da Sie two Arrays übergeben haben. Es ist wie der Versuch, einem Zeiger char *p = {a, b} zwei Adressen zuzuweisen. Ihre Erklärung enthält mehr Elemente als nötig. Siehe Geekforgeeks Erklärung , was ein Arrayzeiger wirklich bedeutet.

Beachten Sie bei der Beantwortung der K & R-Übung 

Option 1:

static char *daytab[2] = { 
    (char []) {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    (char []) {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };} 

oder Option 2:

static char (*daytab)[13] = (char [][13]) { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };} 

Option 1 ist ein Array von zwei char-Zeigern. 

Option 2 ist ein Arrayzeiger. Es zeigt auf ein Array von 13 char-Elementen. Genauso wie Sie einen char-Zeiger inkrementieren können, um den nächsten Buchstaben in einer Zeichenfolge zu erhalten, können Sie diesen Arrayzeiger erhöhen, um das nächste Array von 13 chars zu erfassen.

0
khlau