Der eindimensionale Zugriff auf ein mehrdimensionales array: ist es gut definiert Verhalten?

Ich vorstellen, wir sind uns alle einig, dass es als idiomatischer C, um den Zugriff auf eine multidimensionale Arrays dereferenzieren eines (evtl offset) Zeiger auf erstes element in a one-dimensional Mode, z.B.:

void clearBottomRightElement(int *array, int M, int N)
{
    array[M*N-1] = 0;  //Pretend the array is one-dimensional
}


int mtx[5][3];
...
clearBottomRightElement(&mtx[0][0], 5, 3);

Jedoch die Sprache-Anwalt mich davon zu überzeugen braucht, dass das ist eigentlich gut definiert C! Insbesondere:

  1. Gilt die standard-Garantie, dass der compiler nicht gesetzt Polsterung zwischen z.B. mtx[0][2] und mtx[1][0]?
  2. Normalerweise Indizierung über das Ende eines array (anders als ein-auch über das Ende) ist nicht definiert (C99, 6.5.6/8). Also Folgendes ist klar undefined:
    struct {
        int row[3];           //The object in question is an int[3]
        int other[10];
    } foo;
    int *p = &foo.row[7];     //ERROR: A crude attempt to get &foo.other[4];

    Also durch die gleiche Regel würde man erwarten, die im folgenden nicht definiert:

    int mtx[5][3];
    int (*row)[3] = &mtx[0];  //The object in question is still an int[3]
    int *p = &(*row)[7];      //Why is this any better?

    Warum also sollten diese definiert werden?

    int mtx[5][3];
    int *p = &(&mtx[0][0])[7];

Also, was Teil der C-standard erlaubt ausdrücklich das? (Angenommen aus Gründen der Diskussion.)

BEARBEITEN

Beachten Sie, dass ich habe keinen Zweifel, dass dies funktioniert gut in allen Compilern. Was ich mich Abfrage ist, ob dies ausdrücklich durch den standard.

Dieses Posting als Kommentar, da ich nicht sicher bin. AFAIK arrays sind garantiert kontinuierliche in-memory-Strukturen in der Erwägung, dass möglicherweise der Abstand zwischen den Mitgliedern. Wenn man sich den assembler-code des Arrays zugreifen, sollten Sie in der Lage, um zu sehen, dass der Betrieb erfolgt auf der [][] Zugang ist der gleiche wie *(array + x * index + y).
Ich bin keine Sprache-Anwalt, damit ich nicht eine Antwort, jedoch ist dies genau, wie es funktioniert für raster-imaging. Im Grunde alles, was Sie haben, ist, bytes und wissen Sie, wie viele bytes in einer Zeile. Gehen Sie zur nächsten Zeile müssen Sie den Versatz der originalen Zeiger mit der Anzahl der Zeilen*Breite. Also im Fall von gut definierten Daten, ich würde sagen, das ist völlig in Ordnung, Codierung.
Oh, ich habe keinen Zweifel, dass es in Ordnung ist! Ich verwende dieses Prinzip jeden Tag, und so auch alle anderen. Ich bin rein bitten, von einer Sprache-Anwalt Pedanterie Sicht!
Gut, Juristen sind schrecklich Entwickler. Im Speicher, das array hat keine Polsterung und, daher, die Indizierung mehrdimensionaler arrays als Einzel-dimensional wird immer funktionieren. Ihre Zeiger-Inkrement ergibt sich aus der base-array-pointer, damit arr[10] werden müssen, arr + 10 * sizeof(arr), die in den Spezifikationen bin ich mir sicher. Dies bedeutet, arr[1][5] mit der zweiten dimension immer 5 lange ist: arr + 1 * 5 * sizeof(arrType) + 5 * sizeof (arrType)...
Ich habe nicht die Zeit, es zu schreiben, aber C99-6.5.2.1 die Absätze 3 und 4 scheinen zu machen, dieses gut definiert

InformationsquelleAutor Oliver Charlesworth | 2011-06-09

Schreibe einen Kommentar