Está en la página 1de 34

Los punteros y elementos dinámicos en C++ con ejemplos y ejercicios resueltos

Los punteros en C++ (o apuntadores) son quizá uno de los temas que más confusión causan al momento de
aprender a programar en C++, sin embargo verás que no es para tanto y que todo depende de dos elementos:
el signo & (ampersand) y el * (asterisco) que los explicaré en breve. Durante este artículo verás entonces
que no es para nada difícil hacer y usar punteros y que además son de gran ayuda al momento de necesitar
valores y estructuras dinámicas, por ejemplo, para crear un array dinámico, con dinámico me refiero a que
su tamaño puede ser establecido en tiempo de ejecución y lo mismo se puede hacer con las matrices (que en
realidad son un array multidimensional).

Muy bien para comenzar veamos un pequeño ejemplo y luego su correspondiente explicación, una excelente
forma de aprender. No te preocupes de entender todo con este primer ejemplo, pues durante el resto del
artículo explicaré cada componente, su sintaxis y el final, cómo aprovechar dichas funcionalidades para
nuestro beneficio junto con algún ejercicio.

Ejemplo de punteros

int variable; //Creamos un entero

int * apuntador = &variable;//Creamos una apuntador a la posición en memoria de "variable"

*apuntador = 20; //Le asignamos un valor a esa posición de memoria.

delete [] apuntador; //Después de operar con punteros es necesario liberar la memoria.

puntero = NULL;

Muy bien, ya hemos creado y usado nuestro primer puntero ¿Notaste el uso del asterisco y del ampersand?
espero que sí y además de eso hay otros detalles que debemos considerar, veamos:

Detalles al crear y usar punteros en C++

El tipo de dato del apuntador debe coincidir con el de la variable cuya posición en memoria apuntan. En el
ejemplo vemos que tanto variable como apuntador son enteros.

Siempre que queremos usar el apuntador debemos anteponer el asterisco (*) para indicar que usaremos el
valor en la posición de memoria apuntada.

De no usar el asterisco el comportamiento sería impredecible. Estaremos haciendo uso de la dirección de


memoria más no del valor almacenado en ésta.
Después de usar un puntero, especialmente si trabajamos con arreglos o matrices, es MUY recomendable
liberar la memoria utilizada con la función delete (tal como en el ejemplo)

Un puntero o apuntador puede ser de cualquier tipo de dato, inclusive los podemos usar con tipos complejos.

Ya que sabemos algunos trucos y detalles sobre los apuntadores en C++, vamos a definir formalmente la
utilidad del operador & y del asterisco.

Los punteros y el ampersand

El ampersand es un operador de C++ y es comúnmente utilizado para los punteros. Este operador nos
permite obtener la dirección de memoria de una variable cualquiera y es justo esto (la dirección en memoria)
lo que utilizan los punteros para referenciar valores.

Los apuntadores y el asterisco

El asterisco es, por decirlo de alguna forma, el operador por excelencia de los punteros. SU utilidad radica
en que si el valor de dicho apuntador corresponde a una dirección de memoria, el asterisco nos permite
resolverla y acceder al valor almacenado allí. Viéndolo desde otro enfoque, un apuntador es únicamente una
dirección de memoria (un número) y el asterisco es el que hace la magia de obtener el valor referenciado por
dicha dirección.

Veamos otro ejemplo con cada elemento detallado paso a paso

Ejemplo de apuntadores

char *apuntador = NULL; //Declaramos un puntero

//Es recomendable inicializar un puntero en null, para detectar errores fácilmente

char letra; //Declaramos una variable primitiva

apuntador = &letra; //Asignamos al apuntador la dirección de memoria de la variable primitiva

*apuntador = 'x'; //Modificamos la variable a través del apuntador

cout << letra; //Muestra x por pantalla


En este ejemplo vemos que podemos usar cualquier tipo de dato, que un puntero se puede inicializar
independientemente y luego se le puede asignar su referencia correspondiente. Nótese que al asignar (línea
6) no utilizamos el asterisco, pues estamos definiendo la dirección de memoria y no el valor en dicha
dirección (recuerda que el * resuelve la dirección de memoria y no es lo que requerimos en esa línea).

Ahora que hemos visto los ejemplos y tenemos claro el uso del ampersand y el asterisco podemos entonces
realizar algunos ejercicios interesantes.

Ejercicios con punteros en C++

Parámetros por referencia

Usualmente al enviar un parámetro a una función todo lo que se haga con dicho parámetro allí adentro NO
tiene efecto por fuera. Por ejemplo si a una función la se le envía una variable cuyo valor es diez y al interior
de la función le sumamos un cinco, después de la ejecución de la función el valor de la variable seguirá
siendo diez en vez de quince. Lo que pasó al interior de la función se quedó allí. Para solucionar esto, si
queremos que el valor cambie definitivamente, usamos punteros para pasar no el valor del parámetro sino
una referencia a éste (paso por referencia). Veamos:

#include "iostream"

#include "stdio.h"

using namespace std;

int funcion(int valor)

valor = valor + 10; //Se le suma 10

return valor;

int funcionPunteros(int* valor)

*valor = *valor + 10; //Se le suma 10 a la posición en memoria

return *valor;
}

int main()

int numero = 10;

cout << "Antes de funcion " << numero << "\n"; //10

funcion(numero); //Se pasa por valor

cout << "Despues de funcion " << numero << "\n"; //10

cout << "Antes de funcionPunteros " << numero << "\n"; //10

funcionPunteros(&numero); //Se envía la dirección de memoria y la función resuelve la referencia

cout << "Despues de funcionPunteros " << numero << "\n"; //20 (10+10)

system("pause");

return 0;

Como podrás comprobar si ejecutas el código del ejercicio al llamar a "funcion" sólo enviamos el valor y
por ende éste no es modificado por fuera de la función, con "funcionPunteros" estamos manipulando la
posición en memoria del parámetro recibido (por eso usamos el *) y por ende al ejecutarla el valor de la
variable se modifica. De ese modo ya hicimos el primer ejercicio con punteros en C++ y ya comprendemos
el paso por referencia.

Array dinámico

Como mencioné al comienzo del artículo, por medio de apuntadores podemos crear arreglos o vectores
dinámicos, es decir, un array al cual se le define su tamaño o capacidad durante la ejecución del código y no
antes, lo cual nos permite definirle el tamaño deseado por el usuario.
Para este ejercicio retomaré el ejemplo del artículo de arreglos o vectores: Queremos crear un programa con
el cual podamos guardar los títulos y los autores de diferentes libros sin perder ninguno de ellos. El usuario
es el encargado de suministrar la información de cada libro. En esta ocasión ya sabemos usar punteros, así
que será también el usuario quien nos diga cuántos libros desea ingresar, ya no necesitamos suponer que
sólo ingresará 5 libros. Veamos:

#include "iostream"

#include "stdio.h"

#include "string"

using namespace std;

int main()

string* titulos = NULL; //Se inicializa el puntero (inicia en null)

string* autores = NULL; //Se inicializa el puntero (inicia en null)

int tamanio ; //Se inicializa la variable

cout << "Cuantos libros desea ingresar?";

string entrada;

getline(cin, entrada); //Se asigna el valor ingresado

tamanio = stoi(entrada); //Se transforma la entrada en número

titulos = new string[tamanio]; //Declaramos un arreglo del tamaño ingresado para los titulos

autores = new string[tamanio]; //Declaramos un arreglo del tamaño ingresado para los autores
cout << "Por favor ingrese la siguiente información de los Libros: \n";

for(int i = 0; i < tamanio; i++)

cout << "\n******* Libro " << i + 1 << "********:\n";

cout << "Titulo: ";

//cin >> titulos[i]; //No funciona con espacios

getline(cin, titulos[i]);

cout << "Autor: ";

//cin >> autores[i]; //No funciona con espacios

getline(cin, autores[i]);

//Liberamos la memoria de ambos punteros

delete [] titulos;

delete [] autores;

titulos = NULL;

autores = NULL;

system("pause");

return 0;

Así entonces tuvimos dos punteros, uno para todos los autores y otro para todos los títulos. Haciendo uso de
ellos pudimos definir la cantidad de libros a ingresar por medio del usuario, es decir lo hicimos de manera
dinámica, en tiempo de ejecución.

Matrices dinámicas

Así como lo hicimos con los array, también podemos tener matrices dinámicas y definir su tamaño, número
de filas o número de columnas (o las dos) según sea necesario.
Para esto tomaré el mismo ejemplo de los libros, pero usando una matriz, en vez de dos vectores, tal y como
se solucionó en la sección de matrices veamos:

#include "iostream"

#include "stdio.h"

#include "string"

using namespace std;

int main()

int cols = 2; //El número de columnas es fijo (sólo título y autor)

string** libros; //Si inicializa la matriz (punteros de punteros)

int tamanio ; //Se inicializa la variable

cout << "Cuantos libros desea ingresar?";

string entrada;

getline(cin, entrada); //Se asigna el valor ingresado

tamanio = stoi(entrada); //Se transforma la entrada en número

libros = new string*[tamanio];//Se asigna el número de filas según el usuario

cout << "Por favor ingrese la siguiente información de los Libros: \n";

string titulo ,autor;


for(int i = 0; i < tamanio; i++)

libros[i] = new string[cols]; //Cada fila contendrá dos columnas

//Notar que cols pudo haber sido ingresada por el usuario también

cout << "\n******* Libro " << i + 1 << "********:\n";

cout << "Titulo: ";

getline(cin,titulo);

cout << "Autor: ";

getline(cin,autor);

libros[i][0] = titulo;

libros[i][1] = autor;

//Para liberar la memoria debemos recorrer fila por fila primero.

for (int i = 0; i < tamanio; ++i)

delete [] libros[i]; //Cada fila de libros es otro array de punteros

//Por eso son punteros a punteros

//Luego de limpiar las columnas, quitamos la fila única que quedó

delete [] libros;

system("pause");

return 0;

}
Este ejercicio es el perfecto para aclarar dudas o darse cuenta si realmente comprendes el concepto de
apuntadores y su aplicación para arrays dinámicos. Debido a que la cantidad de columnas es fija, no se lo
pedimos al usuario, simplemente lo declaramos con valor dos. Luego tenemos el puntero, pero no es un
puntero cualquiera, al ser una matriz, será un puntero que tendrá otros punteros adentro, por eso se usa doble
asterisco, luego se obtiene el tamaño del usuario (cantidad de libros) y al momento de inicializar la fila
estamos indicando que es un arreglo de punteros, por eso se usa el * en la línea 23. Luego al interior del
ciclo, cuando estamos llenando la matriz, debemos indicar que cada fila estará compuesta por un array de
punteros de tamaño dos (dos columnas) y así construimos nuestra matriz dinámica.

Debes notar también que la liberación de la memoria es un poco más trabajosa, pues debemos ir fila por fila
liberando la memoria de las columnas creadas y luego liberar la fila completa. Ahí podrás notar la diferencia
en eficiencia y uso de memoria al usar arreglos o usar matrices.

Muy bien, es todo en esta función. Espero haber sido muy claro y que los ejemplos y ejercicios te hayan
servido de mucho. En este momento ya debes saber qué es y cómo hacer un puntero en C++, para qué sirve
el ampersand y el asterisco cuando estamos hablando de apuntadores en C++ y cómo crear arrays dinámicos
y matrices usándolos. No te olvides de dejar un comentario.

PUNTEROS Y GESTIÓN DINÁMICA DE MEMORIA

CONCEPTOS DE PUNTEROS EN C

Un puntero es una variable que contiene como valor una dirección de memoria, que puede ser la dirección
de memoria de otra variable, por tanto, podemos decir que el puntero apunta a otra variable. La variable
apuntada puede ser de cualquier tipo de dato básico (char, int, float, double), derivado (puntero) o
estructurado (tabla, estructura, etc..).
Los punteros tiene una gran utilidad, pues permiten una programación eficaz a nivel de máquina cuando se
maneja la memoria del ordenador.

Su uso en C proporciona las siguientes ventajas:

· En el caso de paso de variables a una función por dirección o referencia, es necesario emplear
parámetros formales como punteros.

· Permiten realizar operaciones de asignación dinámica de memoria.

· Permiten efectuar operaciones con estructuras de datos dinámicas.

Los punteros deben usarse con precaución, ya que pueden provocar fallos en el programa difíciles de
localizar, las causas más corrientes de error en el uso de punteros es:

· Asignación incorrecta de direcciones, por lo que se puede llegar a escribir en zonas de la memoria que
contengan código o datos del programa

· Operaciones incorrectas con los punteros, cuando no se tiene en cuenta el tipo de valor de las variables
apuntadas.

DEFINICION DE PUNTEROS Y ASIGNACIÓN DE DIRECCIONES


a) Definición de variables puntero:

Tipo_básico_de_dato *Nombre_variable_puntero;

Ejemplo:

Int *apunt;

Tipo_básico_de_dato nombre_pnt1, punt2, ...

Ejemplo:

Flota *pnum, *pprec, *pimp;

b) Asignación de direcciones a punteros:


La forma de indicar la dirección de una variable, es utilizando el operador &de tipo monario precediendo al
nombre de la variable, por tanto, hay que diferenciar en una variable, cuando se está empleando su valor
(referenciado por su nombre) o cuando se está empleando su dirección (al preceder su nombre con el
símbolo &).

Int cant;

Cant = 15;

&cant; /* Indica la dirección de la variable cant*/

Para que una variable puntero apunte a otra variable es necesario asignar la dirección de dicha variable al
puntero. El tipo de dato del puntero debe coincidir con el tipo de dato de la variable apuntada, excepto en el
caso de un puntero genérico (con el tipo de dato void). La asignación de la dirección se puede realizar de dos
formas:

a) Por inicialización en la definición del puntero


Float num;

Float *pnum = &num;

b) Por una sentencia de asignación después de haber definido el puntero.

Float nume, *pnum;

Pnum = &nume;

Para visualizar la dirección contenida en un puntero, se puede utilizar el formato %p con la función printf()

Printf(“La dirección contenida en la variable es %p: “,pnum);

Después de tener asignada una dirección a un puntero, durante la ejecución del programa se le puede volver
a asignar la dirección de otra variable, apuntando por tanto a esa variable y abandonando el apuntamiento
anterior.

Float nume, contador;


float *pnum =&nume;

pnum =&contador;

INDIRECCIÓN

Se entiende por indirección la forma de referenciar el valor de una variable a través de un puntero que
apunta a dicha variable. Para realizar la indirección se utiliza el operador monario * que aplicado al nombre
del puntero correspondiente indica el valor de la variable cuya dirección está contenida en dicho puntero.

*Nombre_variable_puntero;

int a = 40, b ; /*Definición de variables*/

int* num = &a; / * Definir una variable puntero*/

pnum = 568; /* Indica el valor de la variable apuntada */


b = *pnum; /* El valor de la variable apuntada se asigna a otra variable*/

int a= 5; b;

int *pnum = &a;

b = pnum + 1; / * se le asigna el valor de a + 1, */

b = *(pnum + 1) / * a la variable b se le asigna el valor contenido en la dirección de memoria obtenida por la


operación aritmética. */

OPERACIONES CON PUNTEROS

ASIGNACIÓN DE PUNTEROS

Int a = 5, b, c;

Int *p1 =&a, *p2;


P2 = p1;

B = *p1;

c = *p2;

ARITMÉTICA DE PUNTEROS

· Sumar o restar un número entero a un puntero.

Nombre_punter + n = Dirección + n *tamaño_tipo_dato

Float num, *punt, *pnum

Punt =&num;

Pnum =punt + 2

/ * Si se se supone que la dirección contenida en punt es 4274, la dirección que contiene ‘pnum’ es 4274 + 2
* 4 = 4282 * /

Char 1 byte

Int 2 bytes

Long int 4 bytes


Float 4 bytes

Double 8 bytes

· Incremento o decremento de punteros

Float *apunt;

Apunt++;

apunt++ /* Incrementa la dirección de apunt y después obtiene el resultado * /

(*apunt)++ / * Incrementa en 1 el valor apuntado por apunt*/

· Resta de dos punteros.

int tabula[10], d;

int *ptab1 = &tabula[1];


int *ptab2 = &tabula[4];

d = ptab1 – ptab2;

d contiene el número de elementos separados por los punteros

COMPARACIÓN DE PUNTEROS

Se utiliza normalmente para la comparación de punteros para conocer las posiciones relativas en memoria
que ocupan las variables apuntadas por punteros.

Int *p1 = &num;

Int *p2 = &cant;

Si efectuamos la comparación p1 > p2 podemos saber qué variable ocupa mayor posición de memoria. Hay
que evitar la confusión de comparar valores.

*p1 > *p2 Compara los valores de las variables apuntadas.


PUNTEROS Y ARRAYS

En el lenguaje C los punteros y los arrays están estrechamente relacionados. Para facilitar su estudio vamos
a diferenciar los casos de arrays unidimensionales (vectores) cadenas de caracteres y arrays
multidimensionales.

Punteros y arrays unidimensionales.

El nombre del array (sin índice) es un puntero que contiene la dirección de memoria del primer elemento del
array. El nombre del array es una constante de tipo puntero y por tanto el compilador no permitirá que se
pueda cambiar en las instrucciones del programa la dirección contenida en el nombre del array.

Int tabula[20];

El empleo de tabula equivale a &tabula[0]

Tabula++; es una operación incorrecta, pues ‘tabula’ es una constante.

Se pueden utilizar variables puntero que contengan la dirección de un array, lo que posibilita la realización
de todas aquellas operaciones permitidas con punteros.
Ejemplo:

Carga la dirección del primer elemento

Int *ptab = tabula; equivale a int *ptab = &tabula[0];

Incrementa el puntero ‘ptab’ (apunta al segundo elemento)

Ptab++

‘ptab’ avanza cuatro elementos (apunta al sexto elemento)

ptab = ptab + 4;
La referencia al valor de un elemento del array se puede hacer por medio de la indirección de un puntero.

Int tabula[30], num;

Int *ptab = tabula;

Num = *(ptab + 4); equivale a num=tabula[4];

Para leer un elemento de un array:

Scanf( “ %d ”, ptab + 6); /* equivale a scanf ( “%d”, &tabula[6] ) */

Para escribir un elemento del array:

Printf( “ %d” , *(ptab + 6 ) ); “equivale a printf(“%d”, tabula[6]); * /

Una vez definido un puntero, se puede indexar como se hace con el nombre de un array.
Int *ptab = tabula

Ptab[0] equivale a *ptab

Ptab[8] equivale a *(ptab + 8)

Esta indexación de punteros sólo es válida cuando se utiliza para apuntar a arrays, siendo errónea en los
demás casos.

Int a, b;

Int *punt = &a;

B = punt[5]; Sentencia errónea.

También es posible utilizar el nombre de un array como un puntero para referenciar a los elementos del
array.

Int vector[40];
*(vector + 3) es equivalente [3]

La diferencia entre el uso del nombre del array como puntero y el uso de un puntero definido
específicamente para contener la dirección del array es que el primero es una constante y siempre debe
apuntar a la misma dirección de memoria (posición del primer elemento del array), mientras que el segundo
es una variable que puede cambiar su contenido o sea que puede contener la direcciónde cualquier elemento
del array, incluso se puede volver a utilizar la variable puntero para apuntar a otro array distinto, siempre
que sus elementos sean del mismo tipo que el definido para el puntero.

Int num[20], cant[8];

Int +*punt =num;

Punt = cant;

El uso de punteros, a pesar de ser más difícil presenta las siguientes ventajas:
· Mayor rapidez en la ejecucióndel programa

· Utilizan menos memoria

INDIRECCIÓN MÚLTIPLE

La indirección múltiple consiste en que un puntero contiene la dirección de otro puntero que a su vez apunta
a una variable. Su formato de definición es el siguiente:

Tipo_dato **Nombre_puntero;

Int cant;

Int *pcan =&cant;

Int **ppcan = &pcan;

**ppcan=57;
printf(“%d”,cant); Visualiza el 57

En realidad se está utilizando un formato de un array bidimensional de punteros, tal como se describia en el
apartado anterior para arrays de punteros a cadenas.

Char nom[35];

Char *pnom = nom;

Char **ppnom = &pnom;

Gets(*ppnom);

Printf(“%s”,nom);

La indirección múltiple se puede extender a más niveles, sin embargo, no es conveniente pasar del nivel **
de puntero a puntero, pues se presentan dificultadoes de seguimiento en el programa.

FUNCIONES DE ASIGNACIÓN DINÁMICA DE MEMORIA


Hasta ahora solo hemos manejado estructuras de datos que se caracterizan porque obligaban de antemano un
tamaño y estructura para que en tiempo de compilación se reservase en memoria el suficiente espacio para
ellas (estructura de datos estáticas), permaneciendo invariables a lo largo de la ejecución del programa. Pero
existe una segunda manera de almacenar y tratar la información sobre la memoria principal y que es
mediante la asignación dinámica de memoria. Este segundo nivel nos da opción a reservar el espacio que
necesitemos en memoria durante la ejecución del programa permitiéndonos posteriormente suliberación,
dando la posibilidad de que en otra parte del programa se use en otro momento la misma zona de memoria
con un cometido diferente.

Esta manera de utilizar la memoria la podemos repetir tantas veces como sea necesario durante la ejecución
de un programa, teniendo siempre la precaución de ir liberando aquellas porciones o parcelas de memoria
reservadas anteriormente y que ya no vamos a volver a utilizar.

Las funciones de la libreria que el ANSI C define para las operaciones de asignación dinámica de memoria
son las descritas a continuación:

Void *calloc(size_t num, size_t tam);

Se encuentra en la libreria stdlib.h, devuelve un puntero al primer byte de la parcela o porción de memoria
reservada o un puntero NULL, en el caso de no haberse podido reservar el bloque de memoria solicitado.
Reserva un bloque de memoria para almacenar ‘num’ elementos de ‘tam’ bytes cada uno de ellos.

Los argumentos son necesarios para la utilización de calloc() son;

· num: indica el número de elementos con la misma estructura que ocuparán la parcela de memoria
reservada.
· Tam:indica el tamaño en bytes de cada uno de los elementos que van a ocupar la parcela de memoria
reservada.

La cantidad de memoria reservada, viene determinada por el resultado que se obtiene al multiplicar el
número de elementos a almacenar en el bloque por el tamaño en bytes de cada uno de esos elementos, es
decir num*tam

Ejemplo:

#include <stdio.h>

#include <stdlib.h>

int *reserva_memoria(int num_element)

int *pt;

pt = (int *) calloc (num_element, sizeof(int));

if (!pt)
{

printf(“Imposible reservar memoria.\n”);

...

return pt;

Void *malloc(size_t tam);

Se encuentra en la libreria stdlib.h, devuelve un puntero al primer byte de la parcela o porción de memoria
reservada o un puntero NULL, en caso de no haberse podido reservar el bloque de memoria solicitado.

Los argumentos necesarios para la utilización de la función malloc son:

· tam: Indica el tamaño en bytes del bloque de memoria que se desea reservar. Es muy importante
comprobar que el puntero devuelto por malloc() no es un puntero nulo antes de hacer uso de él.
Void free(void *puntero);

Se encuentra en la libreria stdlib.h, no devuelve ningún valor. Libera la parcela de memoria apuntada por el
puntero y que previamente habia sido asignado mediante malloc() o calloc(), dando la posibilidad a que
dicho bloque de memoria se pueda volver a asignar posteriormente.

Los argumentos necesarios para la función free son():

*Puntero: variable puntero que debe conteener la dirección de memoria del primer byte del bloque de
memoria que queremos liberar.

#include <stdio.h>

#include <stdlib.h>

main()

char *nombres[50];
int j;

se reserva espacio de memoria de 50 nombres

for (j = 0 ; j < 50; j + + )

if((nombres[j] = (char *) malloc(45)) = NULL)

printf(“Memoria insuficiente. \n”);

exit (0);

gets(nombres[j]);

}
/* Se libera la memoria ocupada */

for (j=0; j < 50 ; j + +)

free ( nombres[j]);

Void *realloc (void *ptr, size_t nuevotam);

Se encuentra en la libreria stdlib.h. Devuelve un puntero al nuevo bloque de memoria reservado o un


puntero nulo (NULL) en el caso de que la operación no se realice con

éxito.

Cambia el tamaño del bloque de memoria apuntada por ‘ptr’ al nuevo tamaño indicado por ‘nuevotam’.
Los argumentos necesarios para la utilización de la función realloc() son:

· ptr: puntero que apunta al bloque de memoria reservado.

· Nuevotam: Valor en bytes que indica el nuevo tamaño del bloque de memoria apuntado por ‘ptr’ y que
puede ser mayor o menor que el tamaño original.

#include <stdio.h>

#include <stdlib.h>

main()

char saludo[] = “Hola”;

char nombre[] = “Juan”;

char *pt;

int i;
pt = (char *) malloc (5);

if (!pt)

printf(“Memoria insuficiente. \n”);

exit (1);

pt = (char *) saludo;

for (j = 0; j < 5; j + +)

printf(“%c”,*(pt+j));

pt = (char *) realloc (pt, 10);


if(!pt)

printf(“Imposible reservar memoria. \n”);

exit(1);

strcat(pt, nombre);

printf(“\%s”, pt);

free(pt);

También podría gustarte