[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