[C con Clase] Cambiar el tipo de un puntero, p.ej de int* a int**, en runtime
Steven Davidson
srd4121 en njit.edu
Mie Ago 27 22:03:27 CEST 2008
Hola Carles,
carles wrote:
> Hola
>
> He intentado usar variables anónimas y he tenido el mismo problema de
> cambio de tipo. Creo que no es posible tener un puntero para, en
> tiempo de ejecución, asignarle un tipo diferente.
> He implementado mi programa empleando un puntero unsigned int*, y uso
> una función que calcula el índice del vector dependiendo de las n
> coordenadas por direccionamiento tradicional:
> (...((coord1)*base+coord2)*base+ ...)+coordN
> Esto hace que se puedan acceder a todos los elementos del vector y
> puedo simular n dimensiones en cualquier momento como si fuera
> matrix[coord1][coord2]...[coordN].
> He encontrado un inconveniente y es que "base" siempre tiene que ser
> igual para cada una de las coordenadas es decir puedo tener matrices
> tipo matriz[4][4]...[4] o matriz[base][base]...[base] pero no puedo
> tener matrices tipo matriz[1][2][3][4]...[N]. De todos modos tal como
> lo tengo hasta ahora me sirve perfectamente.
>
No veo por qué estás forzado a usar siempre la misma "base". Si quieres
varias dimensiones pero que sean variables, entonces necesitas una lista
que contenga las diferentes dimensiones. Por ejemplo,
int *pMatriz;
int *pDim; // Las diferentes cantidades para cada dimensión
int nCant; // Cantidad de dimensiones = Cantidad de elementos en 'pDim'
Para acceder a un elemento, hacemos lo siguiente,
pMatriz[ indice0*pDim[1]*pDim[2]*pDim[3]*...*pDim[nCant-1] +
indice1*pDim[2]*pDim[3]*...*pDim[nCant-1] +
indice2*pDim[3]*...*pDim[nCant-1] +
...
indiceN
]
Como puedes ver esto es bastante engorroso. Seguro que te has dado
cuenta previamente y por eso elegiste otro cálculo para el caso de una
sola "base". Este algoritmo que has implementado se parece mucho al
método de Horner. El resultado es:
pMatriz[ indiceN +
pDim[nCant-1]*( indiceN_1 + // indiceN_1 => "indice N-1"
pDim[nCant-2]*( ... (... +
pDim[2]*( indice1 +
pDim[1]*( indice0 ))...))
]
También puedes ver que realmente no necesitamos la primera dimensión
'pDim[0]' para calcular el índice del elemento a acceder. Por esta
razón, en C/C++, no tenemos que indicar la primera dimensión al
"declarar" un array en un prototipo. Por ejemplo,
void func( int array[][10] )
{
array[4][2] = 4;
}
int main()
{
int tabla[30][10];
func( tabla );
...
}
No necesitamos indicar la primera dimensión del array, porque no se
tiene en cuenta en el cálculo de cualquier índice para tal array. En el
ejemplo anterior, C/C++ calcula lo siguiente:
array[ 4*10 + 2 ]
Otra posibilidad es averiguar la dirección de memoria de cada dimensión.
Por ejemplo,
array[4][2] => (&array[4*10])[2]
O si lo prefieres, usamos un puntero auxiliar:
int *ptr = array;
ptr += 4*10;
ptr += 2;
Ahora 'ptr' apunta al elemento 'array[4][2]'.
En tu caso, podríamos hacer algo similar:
int *ptr = matriz;
ptr += indice0 * pDim[1]*pDim[2]*pDim[3]*...*pDim[nCant-1];
ptr += indice1 * pDim[2]*pDim[3]*...*pDim[nCant-1];
ptr += indice2 * pDim[3]*...*pDim[nCant-1];
...
ptr += indiceN_1 * pDim[nCant-1];
ptr += indiceN;
Por supuesto, podemos aplicar el método de Horner para optimizar estos
cálculos. Esto sería algo como lo siguiente:
ptr = indice0;
ptr *= pDim[1];
ptr += indice1;
ptr *= pDim[2];
ptr += indice2;
ptr *= pDim[3];
...
ptr += indiceN_1;
ptr *= pDim[nCant-1];
ptr += indiceN;
ptr += matriz;
Espero que esto te oriente.
Steven
Más información sobre la lista de distribución Cconclase