|
INICIALIZACION DE ARRAYS DE PUNTEROS
Los arrays de punteros pueden ser inicializados
de la misma forma que un array común , es decir dando los valores de sus elementos ,
durante su definición , por ejemplo si quisieramos tener un array donde el subíndice de
los elementos coincidiera con una letra de las vocales , podríamos escribir :
char *vocales[] = {
"letra no válida" ,
"a" ,
"e" ,
"i" ,
"o" ,
"u" ,
}
Igual que antes, no es necesario en este caso
indicar la cantidad de elementos , ya que el compilador los calcula por la cantidad de
términos dados en la inicialización. Asi el elemento vocales[0] será un puntero con la
dirección del primer string, vocales[1], la del segundo, etc.
PUNTEROS A ESTRUCTURAS
Los punteros pueden también servir para el
manejo de estructuras , y su alojamiento dinámico , pero tienen además la propiedad de
poder direccionar a los miembros de las mismas utilizando un operador particular , el
-> , (escrito con los símbolos "menos" seguido por "mayor" ).
Supongamos crear una estructura y luego asignar
valores a sus miembros:
struct conjunto {
int a ;
double b ;
char c[5] ;
} stconj ;
stconj.a = 10 ;
stconj.b = 1.15 ;
stconj.c[0] = 'A' ;
La forma de realizar lo mismo , mediante el uso
de un puntero, sería la siguiente :
struct conjunto {
int a ;
double b ;
char c[5] ;
} *ptrconj ;
ptrconj = (struct conjunto *)malloc( sizeof(
struct conjunto )) ;
ptrconj->a = 10 ;
ptrconj->b = 1.15 ;
ptrconj->c[0] = 'A' ;
En este caso vemos que antes de inicializar un
elemento de la estructura es necesario alojarla en la memoria mediante malloc(), observe
atentamente la instrucción: primero se indica que el puntero que devuelve la función sea
del tipo de apuntador a conjunto (ésto es sólo formal), y luego con sizeof se le da como
argumento las dimensiones en bytes de la estructura.
PUNTEROS COMO PARAMETROS DE FUNCIONES.
Supongamos que hemos declarado una estructura ,
se puede pasar a una función como argumento:
struct conjunto {
int a ;
double b ;
char c[5] ;
} datos ;
void funcion( struct conjunto datos );
Hicimos notar, en su momento, que en este caso la
estructura se copiaba en el stack y así era pasada a la función, con el peligro que esto
implicaba, si ella era muy masiva, de agotarlo.
Otra forma equivalente es utilizar un puntero a la
estructura :
struct conjunto {
int a ;
double b ;
char c[5] ;
} *pdatos ;
void una_funcion( struct conjunto *pdatos ) ;
Con lo que sólo ocupo lugar en el stack para
pasarle la dirección de la misma. Luego en la función, como todos los miembros de la
estructuras son accesibles por medio del puntero, tengo pleno control de la misma.
PUNTEROS COMO RESULTADO DE UNA FUNCION
Las funciones que retornan punteros son por lo
general aquellas que modifican un argumento , que les ha sido pasado por dirección ( por
medio de un puntero ) , devolviendo un puntero a dicho argumento modificado , ó las que
reservan lugar en el Heap para las variables dinámicas , retornando un puntero a dicho
bloque de memoria.
Así podremos declarar funciónes del tipo de:
char *funcion1( char * var1 ) ;
double *funcion2(int i , double j , char *k ) ;
struct item *funcion3( struct stock *puntst ) ;
El retorno de las mismas puede inicializar
punteros del mismo tipo al devuelto , ó distinto , por medio del uso del casting .
Algunas funciones , tales como malloc() y calloc() definen su retorno como punteros a void
:
void *malloc( int tamano ) ;
de esta forma al invocarlas , debemos indicar el
tipo de puntero de deseamos
p = (double *)malloc( 64 ) ;
|