Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
2013
UNAN – LEON
Departamento de Computación
Autor:
Ing. Juan Carlos Antón Soto
Asignatura:
Programación Estructurada
PUNTEROS
PUNTEROS
Introducción
Los punteros son una de las más potentes características de C, pero a la vez uno de
sus mayores peligros. Los punteros permiten acceder directamente a cualquier parte de la
memoria. Esto da a los programas C una gran potencia. Sin embargo son una fuente
ilimitada de errores. Un error usando un puntero puede bloquear el sistema y a veces
puede ser difícil detectarlo.
Un puntero puede apuntar a un objeto de cualquier tipo, incluyendo estructuras,
funciones, etc. Los punteros se pueden utilizar para crear y manipular estructuras de
datos, para asignar memoria dinámicamente y para proveer el paso de argumentos por
referencia en las llamadas a funciones.
Direcciones de variables
¿Qué pasa cuando se declara una variable?
Al declarar una variable se le dice a la computadora que reserve una parte de la memoria
para almacenarla. Cada vez que se ejecute el programa, la variable se almacenará en un
sitio diferente, eso no se puede controlar, depende de la memoria disponible.
Dependiendo del tipo de variable que se declare la computadora reservará más o menos
memoria. Por ejemplo si se declara un char, la computadora reserva 1 byte (8 bits).
Cuando finaliza el programa todo el espacio reservado queda libre.
1
PUNTEROS
Existe una forma de saber qué direcciones ha reservado la computadora. Se trata de usar
el operador & (operador de dirección). Por ejemplo: Se declara la variable 'a' y se obtiene
su valor y dirección.
#include <stdio.h>
void main()
{
int a;
a = 10;
printf( "Dirección de a = %p, valor de a = %d\n", &a, a );
}
Para mostrar la dirección de la variable usamos %p en lugar de %d, sirve para escribir
direcciones de punteros y variables. El valor se muestra en hexadecimal.
No hay que confundir el valor de la variable con la dirección donde está almacenada la
variable. La variable 'a' está almacenada en un lugar determinado de la memoria, ese lugar
no cambia mientras se ejecuta el programa. El valor de la variable puede cambiar a lo largo
del programa. Ese valor está almacenado en la dirección de la variable. El nombre de la
variable es equivalente a poner un nombre a una zona de la memoria. Cuando en el
programa se escribe 'a', en realidad se dice, "el valor que está almacenado en la dirección
de memoria de 'a'".
Para entender mejor lo anterior suponga que se tiene el dibujo siguiente:
2
PUNTEROS
En el dibujo se tiene una representación de lo que sería la memoria de la computadora.
Cada casilla representa un byte de la memoria. Y cada número es su dirección de memoria.
La primera casilla es la posición 00001 de la memoria. La segunda casilla la posición 00002
y así sucesivamente.
Suponga que se declara una variable char: char numero = 43. La computadora guardaría
por ejemplo la posición 00003 para esta variable. Esta posición de la memoria queda
reservada y ya no la puede usar nadie más. Además esta posición a partir de ahora se
llama numero. Como se le ha dado el valor 43 a numero, el valor 43 se almacena en la
posición 00003.
Si se escribe el siguiente programa:
#include <stdio.h>
void main()
{
int numero;
numero = 43;
printf( "Dirección de numero = %p, valor de numero = %d\n", &numero, numero );
}
El resultado sería:
Dirección de numero = 00003, valor de numero = 43
3
PUNTEROS
¿Qué es un puntero?
Un puntero es una variable un tanto especial. Con un puntero se puede almacenar
direcciones de memoria, es decir que se puede tener guardada la dirección de una
variable.
Cuando se declara un puntero se debe especificar el tipo de dato cuya dirección
almacenará. En el siguiente ejemplo se quiere almacenar la dirección de una variable char.
Así que para declarar el puntero punt debemos hacer:
char *punt;
El * (asterisco) sirve para indicar que se trata de un puntero, debe ir justo antes del
nombre de la variable, sin espacios. En la variable punt sólo se pueden guardar direcciones
de memoria, no se pueden guardar datos. Observe el ejemplo anterior un poco ampliado
para ver cómo funciona un puntero:
#include <stdio.h>
void main()
{
int numero;
int *punt;
numero = 43;
punt = №
printf( "Dirección de numero = %p, valor de numero = %d\n", &numero, numero );
}
Véase el ejemplo anterior línea a línea:
•
•
En la primera int numero; se reserva memoria para numero (suponga que queda como
antes, posición 00003). Por ahora numero no tiene ningún valor.
Siguiente línea: int *punt;. Se reserva una posición de memoria para almacenar el
puntero. Lo normal es que según se declaran variables se guarden en posiciones
contiguas. De modo que quedaría en la posición 00004. Por ahora punt no tiene ningún
valor, es decir, no apunta a ninguna variable. Esto es lo que tenemos por ahora:
4
PUNTEROS
•
•
Tercera línea: numero = 43;. Se ha dado el valor 43 a numero. Se almacena 43 en la
dirección 00003, que es la de numero.
Cuarta línea: punt = №. Se da un valor a punt. El valor que le damos es la
dirección de numero (ya se ha visto que & devuelve la dirección de una variable). Así
que punt tendrá como valor la dirección de numero, 00003. Por lo tanto ya se tiene:
Cuando un puntero tiene la dirección de una variable se dice que ese puntero apunta a esa
variable.
NOTA: La declaración de un puntero depende del tipo de dato al que queramos apuntar.
En general la declaración es:
tipo_de_dato *nombre_del_puntero;
Si en vez de querer apuntar a una variable tipo char como en el ejemplo hubiese sido de
tipo int:
int *punt;
¿Para qué sirve un puntero? ¿Cómo se usa?
Los punteros tienen muchas utilidades, por ejemplo permiten pasar argumentos (o
parámetros) a una función y modificarlos. También permiten el manejo de cadenas y de
arrays. Otro uso importante es que permiten acceder directamente a la pantalla, al
teclado y a todos los componentes de la computadora.
Pero si sólo sirvieran para almacenar direcciones de memoria no servirían para mucho.
Deben dejar también la posibilidad de acceder a esas posiciones de memoria. Para acceder
a ellas se usa el operador *.
5
PUNTEROS
#include <stdio.h>
void main()
{
int numero;
int *punt;
numero = 43;
punt = №
printf( "Dirección de numero = %p, valor de numero = %d\n", &numero, *punt );
}
Si se observa los cambios con respecto al ejemplo anterior, se ve que para acceder al
valor de numero se usa *punt en vez de numero. Esto es así porque punt apunta a numero y
*punt permite acceder al valor al que apunta punt.
Ahora se ha cambiado el valor de numero a través de *punt.
#include <stdio.h>
void main()
{
int numero;
int *punt;
numero = 43;
punt = №
*punt = 30;
printf( "Dirección de numero = %p, valor de numero = %i\n", &numero, numero );
}
En resumen, usando punt se puede apuntar a una variable y con *punt se cambia el
contenido de esa variable.
Un puntero no sólo sirve para apuntar a una variable, también sirve para apuntar a una
dirección de memoria determinada.
Usando punteros en una comparación
Vea el siguiente ejemplo. Se quiere comprobar si dos variables son iguales usando
punteros:
6
PUNTEROS
#include <stdio.h>
void main()
{
int a, b;
int *punt1, *punt2;
a = 5; b = 5;
punt1 = &a; punt2 = &b;
if ( punt1 == punt2 )
printf( "Son iguales\n" );
}
Se podría pensar que el if se cumple y se mostraría el mensaje “Son iguales” en pantalla.
Pues no es así, el programa es erróneo. Es cierto que a y b son iguales. También es cierto
que punt1 apunta a 'a' y punt2 a 'b'. Lo que se quería comprobar era si a y b son iguales.
Sin embargo con la condición se está comprobando si punt1 apunta al mismo sitio que
punt2, se está comparando las direcciones donde apuntan. Por supuesto a y b están en
distinto sitio en la memoria así que la condición es falsa. Para que el programa funcionara
deberíamos usar los asteriscos:
#include <stdio.h>
void main()
{
int a, b;
int *punt1, *punt2;
a = 5; b = 5;
punt1 = &a; punt2 = &b;
if ( *punt1 == *punt2 )
printf( "Son iguales\n" );
}
Ahora sí. Se está comparando el contenido de las variables a las que apuntan punt1 y
punt2. Se debe tener mucho cuidado con esto porque es un error que se da con mucha
facilidad.
Ahora se cambia un poco el ejemplo. Ahora 'b' no existe y punt1 y punt2 apuntan a 'a'. La
condición se cumplirá porque apuntan al mismo sitio.
7
PUNTEROS
#include <stdio.h>
void main()
{
int a;
int *punt1, *punt2;
a = 5;
punt1 = &a; punt2 = &a;
if ( punt1 == punt2 )
printf( "punt1 y punt2 apuntan al mismo sitio\n" );
}
Operaciones con punteros
Operación de asignación =
A un puntero se le puede asignar una dirección de memoria concreta, la dirección de
una variable o el contenido de otro puntero.
Una dirección de memoria concreta:
int *ptr;
...
ptr = 0x1F3CE00A;
...
La dirección de una variable del tipo al que apunta el puntero: char c;
char *ptr;
...
ptr = &c;
Otro puntero del mismo tipo: char c;
char *ptr1;
char *ptr2;
…
ptr1 = &c;
ptr2 = ptr1;
8
PUNTEROS
Ejemplo
Programa que suma un valor a una variable a través de un puntero
#include <stdio.h>
void main()
{
int a, *p;
a=5;
printf("\n\nEl valor inicial de a = %d y su dirección de memoria es : %p\n", a, &a);
p=&a;
printf("\np = &a\n\np = %p y *p = %d", p, *p);
*p+=7;
printf("\n\nEl contenido de *p se suma con el valor 7\n\n");
printf("\nEl valor final de la variable a = %d y el contenido de *p = %d\n\n", a,*p);
}
Su resultado es el siguiente:
El valor inicial de a = 5 y su dirección de memoria es 0012FF84
p = &a
p = 0012FF84 y *p = 5
El contenido de *p se suma con el valor 7
El valor final de la variable a = 12 y el contenido de *p = 12
PUNTERO NULO
Un puntero se puede inicializar como cualquier otra variable, aunque los únicos valores
significativos son NULL o la dirección de un objeto previamente definido.
NULL es una constante definida en el fichero stdio.h, cuando un puntero apunta a
NULL significa que apunta a la dirección 0 del sistema, y está a la espera de que se le
asigne una dirección válida. La siguiente sentencia no se debe realizar:
int *px = 103825;
Ya que el sistema es el encargado de asignar las direcciones y por lo tanto el usuario
no sabe acerca de la dirección 103825.
9
PUNTEROS
Errores comunes sobre punteros
Asignar punteros de distinto tipo
int a = 10;
int *ptri = NULL;
double x = 5.0;
double *ptrf = NULL;
ptri = &a;
ptrf = &x;
ptrf = ptri; // ERROR
Utilizar punteros no inicializados char *ptr;
*ptr = ‘a’; // ERROR
Asignar valores a un puntero y no a la variable a la que apunta int n;
int *ptr = &n;
ptr = 9; // ERROR
Intentar asignarle un valor al dato apuntado por un puntero cuando éste es NULL int *ptr = NULL;
*ptr = 9; // ERROR
Punteros y arrays
En C existe, entre punteros y arrays, una relación tal que, cualquier operación que se
pueda realizar mediante la indexación de un array, se puede realizar también con
punteros.
Cuando declaramos un vector
tipo identificador
[dim]
10
PUNTEROS
En realidad
1. Reservamos memoria para almacenar dim elementos de tipo tipo.
2. Creamos un puntero identificador que apunta a la primera posición de la
memoria reservada para almacenar los componentes del array.
Por tanto, el identificador del array es un puntero.
Operaciones aritméticas con punteros
A un puntero se le puede sumar o restar un entero.
int *p;
p++;
p--;
p = p + 3;
p = p – 3;
// declara p como un puntero a un entero
// hace que p apunte al siguiente entero
// hace que p apunte al entero anterior
// avanzar tres enteros
// retroceder tres enteros
Ejemplo de punteros con operaciones aritméticas
#include <stdio.h>
void main()
{
int a = 2, b = 5, c[] = {1,10,30,44}, i, j, *pa, *pb, *pc;
printf("\n\tValores iniciales\n");
printf("\t*****************\n");
printf("\t%s %5s %5s %5s\n", "a", "&a", "b", "&b");
printf("\t%d %5p %3d %5p\n\n", a, &a, b, &b);
for (i = 0, j = 0; i < 4; i++, j++)
printf("c[%d] = %3d &c[%d] = %p\n", i, c[i], j, &c[i]);
pa = &a; // pa apunta a la direccion de a
printf("\n\npa = &a pa = %p, *pa = %d\n\n",pa, *pa);
b = *pa + 1; // se le está sumando 1 al valor apuntado por pa y luego se asigna a b
printf("b = *pa + 1 b = %d\n\n",b);
pc = c; //pc apunta al arreglo c
printf("pc = c\n\n pc = %p\n\n", pc);
11
PUNTEROS
printf("el puntero pc se desplaza una posicion de memoria y asigna ese contenido a \'b\' \n ");
b = *(pc + 1); // pc se desplaza una posicion de memoria y asigna ese contenido a b
printf("\nb = *(pc + 1) b = %d\n", b);
printf("\npb = &b\n");
pb = &b;
printf("pb = %p , direccion de b = %p, b = %d\n\n",pb,&b,b);
printf("*pb = 0\n");
*pb = 0; // el contenido de pb es puesto a cero
printf("\n*pb += 2 La variable b indirectamente se incrementa en 2 unidades\n\n");
*pb += 2; // la variable b indirectamente se incrementa en dos unidades
printf("*pb = %d , b = %d\n\n",*pb,b);
printf("La variable b indirectamente se decrementa en 1 unidad\n\n");
(*pb) --; // La variable b indirectamente se decrementa en una unidad
printf("*pb = %d , b = %d\n\n",*pb,b);
}
El resultado sería el siguiente:
Valores iniciales
*****************
a &a b
2 0012ff50 5
&b
0012ff54
c[0] =
c[1] =
c[2] =
c[3] =
1
10
30
44
&c[0]: 0012ff58
&c[1]: 0012ff5c
&c[2]: 0012ff60
&c[3]: 0012ff64
pa = &a pa = 0012ff50, *pa = 2
b = *pa + 1 b = 3
pc = c
pc = 0012ff58
el puntero pc se desplaza una posicion de memoria y asigna ese contenido a \'b\' \n ");
b = *(pc + 1) b = 10
pb = &b
pb = 0012ff54 , direccion de b = 0012ff54, b = 10
*pb = 0
*pb += 2 La variable b indirectamente se incrementa en 2 unidades
*pb = 2 , b = 2
La variable b indirectamente se decrementa en 1 unidad
*pb = 1 , b = 1
12
PUNTEROS
Utilizando la aritmética de punteros nos desplazamos de unas posiciones de memoria
a otras. Pero ¿cómo acceder a los contenidos de esas posiciones utilizando notación de
punteros?
Empleando el operador *, indirección que nos da el contenido de la dirección de
memoria apuntada.
Ejemplo:
Analice el siguiente programa, escrito primeramente con matrices y a continuación
con punteros.
// versión utilizando una matriz unidimensional
#include <stdio.h>
void main()
{
int lista[ ] = {24,30,15,45,34};
int indice;
for(indice = 0; indice < 5; indice ++)
printf(“\t%d”,lista[indice]);
printf(“\n\n”);
}
El resultado sería el siguiente:
24
30
15
45
34
13
PUNTEROS
En este ejemplo se ha utilizado la indexación, expresión lista[indice], para acceder a
los elementos de la matriz lista. Cuando se interpreta ésta expresión se sabe que a partir
de la dirección de comienzo de la matriz, esto es, a partir de lista, tiene que avanzar
indice elementos para acceder al contenido del elemento especificado por ese índice.
//versión con punteros
#include <stdio.h>
void main()
{
int lista[ ] = {24,30,15,45,34};
int indice;
for(indice = 0; indice < 5; indice ++)
printf(“\t%d”,*(lista + indice));
}
Esta versión es idéntica a la anterior, excepto que la expresión para acceder a los
elementos del array es: *(lista + indice). Esto deja constancia de que lista es la dirección
de comienzo del array. Si a esta dirección le sumamos 1, dicho de otra manera si indice
vale 1, nos situamos en el siguiente entero de lista; esto es *(lista + 1) y lista[1]
representan el mismo valor.
Punteros a cadena de caracteres
Puesto que una cadena de caracteres es un array de caracteres, la forma de definir un
puntero a una cadena de caracteres es: char *cadena;
El identificador del array es la dirección de comienzo del array. Para saber dónde
termina la cadena, el compilador añade el carácter ‘\0’ (ASCII 0, NULL):
char *nombre = “PEPE PEREZ”;
14
PUNTEROS
Si se quiere recorrer la cadena con notación de punteros se hace lo siguiente:
#include <stdio.h>
void main ()
{
char *nombre = "PEPE PEREZ";
int i = 0;
do
{
printf("%c", *(nombre+i));
i++;
}while (*(nombre+i));
printf("\n");
}
Muchas funciones de C que trabajan con cadenas de caracteres, utilizan punteros y
devuelven como resultado un puntero. Por ejemplo, la función de C strchr() para localizar
un carácter en una cadena, devuelve un puntero al carácter buscado o un puntero nulo si el
carácter no se encuentra. Ejemplo:
#include <stdio.h>
#include <string.h>
int main()
{
const char *cadena = "FERROCARRIL";
char caracter1 = 'A';
char caracter2 = 'z';
if ( strchr( cadena, caracter1 ) != NULL )
printf( "\n\'%c\' se encuentra en %s\n\n", caracter1, cadena );
else
printf( "\n\'%c\' no se encontro en %s\n\n", caracter1, cadena );
if ( strchr( cadena, caracter2 ) != NULL )
printf( "\n\'%c\' se encontro en %s\n\n", caracter2, cadena );
else
printf( "\n\'%c\' no se encontro en %s\n\n", caracter2, cadena );
return 0;
}
15
PUNTEROS
El siguiente ejemplo copia una cadena de caracteres en otra, utilizando punteros.
#include <stdio.h>
void copia_cadena(char *p, char *q);
void main()
{
char cadena1[50], cadena2[50];
printf("Introducir cadena: ");
gets(cadena1);
copia_cadena(cadena2,cadena1); // copia la cadena1 en la cadena2
printf("\n\tLa cadena copiada es: %s\n\n",cadena2);
}
void copia_cadena(char *p, char *q)
{
while ((*p = *q) != '\0')
{
p ++;
q ++;
}
}
El resultado sería el siguiente:
// copia q en p
Introducir cadena:
Ingenieros en Sistemas de Información
La cadena copiada es: Ingenieros en Sistemas de Información
El bucle formado por la sentencia while, realiza las siguientes operaciones:
1. Toma el carácter contenido en la dirección dada por q y lo copia en la dirección dada
por p.
2. Ve si el contenido de p es el carácter nulo.
3. p pasa apuntar a la siguiente dirección, y lo mismo sucede con q. Si no se dio la
condición de terminación, el proceso se repite desde el inicio.
16
PUNTEROS
Matrices de punteros
Son matrices que contienen elementos de tipo puntero, es decir, cada elemento de la
matriz contiene una dirección en lugar de un dato de tipo primitivo.
Ejemplo:
#include <stdio.h>
void main()
{
int *p[5];
int b = 30;
p[0] = &b;
//matriz de 5 elementos (int *)
// variable de tipo int
// p[0] apunta al entero b
El resultado sería el siguiente:
El contenido de *p[0] = 30
printf (“\n\tEl contenido de *p[0] = %d\n\n”,*p[0]);
}
Un array de dos dimensiones y un array de punteros se pueden usar de forma
parecida, pero no son lo mismo. Ejemplo:
int a[5][5];
int *p[5];
//array bidimensional
//array de punteros
En el ejemplo anterior, el compilador reserva memoria para un array a de 25
elementos de tipo entero y para un array p de 5 elementos declarados como punteros a
objetos de tipo entero.
Si cada uno de los objetos apuntados por los elementos del array p es a su vez un
array de 5 elementos de tipo entero, la ocupación de memoria será la de los 5 elementos
de p más la de los 25 elementos de los 5 array de enteros.
El acceso a los elementos de la matriz p puede hacerse utilizando la notación de
punteros o utilizando la indexación igual que lo haríamos con a.
Por ejemplo para asignar valores a los elementos referenciados por la matriz p y
después visualizarlos sería de la siguiente forma:
17
PUNTEROS
#include <stdio.h>
#define F 5
#define C 5
void main()
{
int a[F][C] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
int *p[F], i, j;
//A cada posición del arreglo de punteros se le está asignando la dirección de memoria de cada
posición del arreglo bidimensional.
for (i = 0; i < F; i++)
p[i] = a[i];
printf("\n\n");
//Impresión de los elementos almacenados en el arreglo bidimensional a través del
//arreglo de punteros.
for (i = 0; i < F; i++)
{
for (j = 0; j < C; j++)
printf("%5d ", p[i][j]);
printf("\n\n");
}
}
El resultado sería el siguiente:
1
6
11
16
21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
¿Cómo se aplica la notación de punteros o aritmética de punteros para desplazarse en
un array bidimensional?
18
Con subíndices Con punteros valor
p[0][0] *(*(p+0)+0) 1
p[0][1] *(*(p+0)+1) 2
p[0][2] *(*(p+0)+2) 3
p[0][3] *(*(p+0)+3) 4
.
.
.
p[4][4] *(*(p+4)+4) 25
PUNTEROS
Existe por tanto una equivalencia:
*p representa un puntero a la primera fila, con *(p+1)+j para las direcciones y
*(*p+1)+j) para los contenidos. El segundo subíndice actúa sobre la columna.
Si en x[10][20] se quiere acceder al elemento de la fila 3 y la columna 6, se hace
escribiendo x[2][5]. Con notación de punteros, es equivalente a *(*(x+2)+5), ya que x+2
es un puntero a la fila 3. Por tanto. El contenido de dicho puntero, *(x+2), es la fila 3. Si
se desplaza 5 posiciones en esa fila se llega a la posición *(x+2)+5, cuyo contenido es
*(*(x+2)+5). Ver dibujo:
19
PUNTEROS
Punteros a punteros
Para especificar que una variable es un puntero a un puntero, la sintaxis utilizada es la
siguiente:
Tipo **varpp;
Donde Tipo especifica el tipo del objeto apuntado después de una doble indirección
(puede ser cualquier tipo incluyendo tipos derivados) y varpp es el identificador de la
variable puntero a puntero.
Por ejemplo: int a, *p, **pp;
a = 10; //dato
p = &a; // puntero que apunta al dato
pp = &p; // puntero que apunta al puntero que a la vez apunta al
// dato
Se dice que p es una variable con un nivel de indirección, esto es, a través de p no se
accede directamente al dato, sino a la dirección que indica dónde está el dato. Haciendo
un razonamiento similar se dice que pp es una variable con dos niveles de indirección.
Ejemplo:
#include <stdio.h>
void main()
{
int a[3][3], *p[3], **q, i,j;
for (i = 0; i < 3; i++)
p[i] = a[i];
q =p;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{ printf("q[%d][%d] = ",i,j);
scanf("%d", &q[i][j]);
}
}
printf("\n\n");
for (i = 0; i < 3; i++)
20
PUNTEROS
{
for (j = 0; j < 3; j++)
printf("%5d ",q[i][j]);
printf("\n");
}
}
El nombre de un array de dos dimensiones no puede considerarse como un puntero a
puntero. La siguiente asignación daría un error.
int a[5][5];
int **p = a; //diferentes niveles de indirección
21
PUNTEROS
EJERCICIOS PROPUESTOS
PUNTEROS
1. Encuentre los errores en la siguiente declaración de punteros.
int x, *p;
char *b = “Cadena Larga”;
char *car = ‘C’;
x = 6;
p = x;
p = b;
2. Encuentre el error del siguiente programa y de una solución para poder ejecutarlo sin
ningún fallo.
#include <stdio.h>
int main()
{
int *a, b = 5;
*a = 5;
printf("*a = %d y b = %d\n\n", a, b);
}
3. En el siguiente código se accede a los elementos de una matriz. Acceder a los mismos
elementos a través de punteros.
#define N 4
#define M 5
int f, c;
float mt[N][M];
…
for (f = 0; f < N; f++)
{
for (c = 0; c < M; c++)
printf(“%f”,mt[N][M]);
printf(“\n\n”);
}
22
PUNTEROS
4. Escriba un programa que de un valor a una variable. Esta sea apuntada por un puntero y
sumarle 10 a través del puntero. Luego imprima el resultado.
5. Calcule la longitud de una cantidad de caracteres ingresada por el teclado y visualice las
letras que contiene.
6. Escriba un programa en C que cuente el número de veces que aparece un carácter en
una cadena de N caracteres.
7. Realice un programa que pida por teclado el tamaño de un arreglo y que almacene en él
números enteros aleatorios. Para recorrer el arreglo se pide utilizar punteros en lugar
de índices.
23