Domanda

Questo è venuto fuori da questa risposta ad una mia domanda precedente.È garantito che il compilatore tratti array[4][4] lo stesso di array[16]?

Ad esempio, una delle seguenti chiamate a api_func() stai attento?

void api_func(const double matrix[4][4]);

// ...

{
  typedef double Matrix[4][4];

  double* array1 = new double[16];
  double array2[16];

  // ...

  api_func(reinterpret_cast<Matrix&>(array1));
  api_func(reinterpret_cast<Matrix&>(array2));
}
È stato utile?

Soluzione

Dallo standard C++, facendo riferimento a sizeof operatore:

Quando applicato a un array, il risultato è il numero totale di byte nell'array.Ciò implica che la dimensione di un array di n elementi è n volte la dimensione di un elemento.

Da questo direi che double[4][4] E double[16] dovrebbe avere la stessa rappresentazione sottostante.

Cioè, dato

sizeof(double[4]) = 4*sizeof(double)

E

sizeof(double[4][4]) = 4*sizeof(double[4])

Poi abbiamo

sizeof(double[4][4]) = 4*4*sizeof(double) = 16*sizeof(double) = sizeof(double[16])

Penso che un compilatore conforme agli standard dovrebbe implementarli allo stesso modo, e penso che questo non sia qualcosa che un compilatore potrebbe interrompere accidentalmente.Il modo standard di implementare gli array multidimensionali funziona come previsto.Infrangere lo standard richiederebbe lavoro extra, probabilmente senza alcun beneficio.

Lo standard C++ afferma inoltre che un array è costituito da elementi allocati in modo contiguo, il che elimina la possibilità di fare qualcosa di strano utilizzando puntatori e riempimento.

Altri suggerimenti

Non penso che ci sia un problema con il riempimento introdotto avendo a multidimensionale vettore.

Ogni elemento di un array deve soddisfare i requisiti di riempimento imposti dall'architettura.Un array [N][M] avrà sempre la stessa rappresentazione in memoria di uno di [M*N].

Ogni elemento dell'array dovrebbe essere disposto in sequenza in memoria dal compilatore.Le due dichiarazioni, sebbene di tipo diverso, hanno la stessa struttura di memoria sottostante.

@Konrad Rudolph:

Io stesso ho confuso questi due (riga maggiore/colonna maggiore), ma so questo:E' ben definito.

int x[3][5], ad esempio, è un array di dimensione 3, i cui elementi sono array int di dimensione 5.(§6.5.2.1) Aggiungendo tutte le regole dello standard su array, indirizzamento, ecc.si ottiene che il secondo pedice fa riferimento a numeri interi consecutivi, mentre il primo pedice fa riferimento a oggetti consecutivi di 5 int.(Quindi 3 è il numero più grande;hai 5 int in mezzo x[1][0] e x[2][0].)

Sarei preoccupato che venga aggiunto il riempimento per cose come Matrix[5] [5] per allineare le parole di ogni riga, ma potrebbe essere semplicemente una mia superstizione.

Una domanda più grande è:hai davvero bisogno di eseguire un cast del genere?

Anche se tu Potrebbe riuscire a farla franca, sarebbe comunque più leggibile e gestibile evitarlo del tutto.Ad esempio, potresti utilizzare in modo coerente double[m*n] come tipo effettivo e quindi lavorare con una classe che racchiude questo tipo e magari sovraccarica l'operatore [] per facilità d'uso.In tal caso, potresti anche aver bisogno di una classe intermedia per incapsulare una singola riga, in modo che codice come my_matrix[3][5] funzioni ancora come previsto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top