Pregunta

Esto surgió de esta respuesta a una pregunta anterior mía.¿Está garantizado que el compilador trate array[4][4] lo mismo que array[16]?

Por ejemplo, ¿alguna de las siguientes llamadas a api_func() ¿estar a salvo?

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));
}
¿Fue útil?

Solución

Del estándar C++, refiriéndose al sizeof operador:

Cuando se aplica a una matriz, el resultado es el número total de bytes en la matriz.Esto implica que el tamaño de una matriz de n elementos es n veces el tamaño de un elemento.

De esto yo diría que double[4][4] y double[16] tendría que tener la misma representación subyacente.

Es decir, dado

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

y

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

entonces nosotros tenemos

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

Creo que un compilador compatible con los estándares tendría que implementarlos de la misma manera, y creo que esto no es algo que un compilador rompería accidentalmente.La forma estándar de implementar matrices multidimensionales funciona como se esperaba.Romper el estándar requeriría trabajo extra, sin probable beneficio alguno.

El estándar C++ también establece que una matriz consta de elementos asignados de forma contigua, lo que elimina la posibilidad de hacer algo extraño utilizando punteros y relleno.

Otros consejos

No creo que haya ningún problema con el relleno introducido al tener un multidimensional formación.

Cada elemento de una matriz debe satisfacer los requisitos de relleno impuestos por la arquitectura.Una matriz [N][M] siempre tendrá la misma representación en memoria que una de [M*N].

El compilador debe colocar cada elemento de la matriz de forma secuencial en la memoria.Las dos declaraciones, aunque de diferentes tipos, tienen la misma estructura de memoria subyacente.

@Konrad Rudolph:

Yo mismo confundo esos dos (fila principal/columna principal), pero sí sé esto:Está bien definido.

int x[3][5], por ejemplo, es una matriz de tamaño 3, cuyos elementos son matrices int de tamaño 5.(§6.5.2.1) Agregar todas las reglas del estándar sobre matrices, direccionamiento, etc.obtienes que el segundo subíndice hace referencia a números enteros consecutivos, mientras que el primer subíndice hará referencia a objetos consecutivos de 5 int.(Entonces 3 es el número mayor;tienes 5 entradas entre x[1][0] y x[2][0].)

Me preocuparía que se agregue relleno a cosas como Matrix[5][5] para alinear cada palabra de fila, pero eso podría ser simplemente mi propia superstición.

Una pregunta más importante es:¿Realmente necesitas realizar un reparto así?

Aunque tú podría Si pudiera salirse con la suya, aún sería más legible y fácil de mantener evitarlo por completo.Por ejemplo, podría usar consistentemente double[m*n] como el tipo real y luego trabajar con una clase que englobe este tipo y tal vez sobrecargue el operador [] para facilitar su uso.En ese caso, es posible que también necesites una clase intermedia para encapsular una sola fila, de modo que código como my_matrix[3][5] siga funcionando como se esperaba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top