Lenguaje C [Apuntadores y arreglos]

Anuncio
Lenguaje C [Apuntadores y arreglos]
M. en C. Sergio Luis Pérez Pérez
UAM C UAJIMALPA , M ÉXICO, D. F.
Trimestre 14-O
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
1 / 20
Apuntadores y direcciones
Apuntadores y direcciones
1
Apuntadores y direcciones
2
Apuntadores y arreglos
3
Apuntadores a caracteres
4
Arreglos de apuntadores y multidimensionales
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
2 / 20
Apuntadores y direcciones
Apuntadores y direcciones I
Un apuntador es una variable que contiene la dirección de una
variable.
El operador unario ∗ es el operador de indirección o
desreferencia, de manera que cuando se aplica un apuntador se
tiene acceso al objeto que señala.
El operador & sólo se puede aplicar a objetos que están en
memoria, es decir variables y elementos.
El operador & no puede aplicarse a expresiones, constantes o
variables tipo registro.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
3 / 20
Apuntadores y direcciones
Apuntadores y direcciones II
La declaración de un apuntador como:
int ∗ ip;
funciona como mnemónico y dice que la expresión *ip es un int.
Ejemplo 1
int x = 1, y = 2, z[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *ip, *iq, i;
ip = &x;/*ip apunta a x*/
y = *ip;/*y ahora vale 1*/
*ip = 0;/*x ahora vale 0*/
ip = &z[0];/*ip apunta a 0 de z[0]*/
printf(“ %d %d %d %d %d\n”, x, y, *ip, z[0], ip);
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
4 / 20
Apuntadores y direcciones
Apuntadores y direcciones III
Ejemplo 1 continuación
*ip = *ip + 10;
iq = ip;/*iq apunta a lo mismo que ip*/
for(i = 0; i < 10; i++, ip++)
printf(“ %d\n”, *ip);
ip = iq;/*ip apunta a lo que apuntaba originalmente*/
Debido a que C pasa los argumentos por valor si se desea hacer
una especie de paso por referencia es necesario pasar las
variables como &variable pues debido a que & produce la
dirección de una variable entonces &variable es un apuntador.
intercambia(&a, &b)
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
5 / 20
Apuntadores y direcciones
Apuntadores y direcciones IV
Intercambia
void intercambia(int *a, int *b){
int temporal = *a;
*a = *b;
*b = temporal;
return;
}
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
6 / 20
Apuntadores y arreglos
Apuntadores y arreglos
1
Apuntadores y direcciones
2
Apuntadores y arreglos
3
Apuntadores a caracteres
4
Arreglos de apuntadores y multidimensionales
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
7 / 20
Apuntadores y arreglos
Apuntadores y arreglos I
La relación entre apuntadores y arreglos en el caso de lenguaje
de C es muy estrecha.
Cualquier operación que pueda lograrse por indexación de un
arreglo también puede lograrse con apuntadores.
La versión con apuntadores tenderá a ser más rápida pero difı́cil
de entender.
Ejemplo 2
int v[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, *pv;
pv = &v[0];
for(i = 0; i < 10; i++)
printf(“ %d %d\n”, *(pv+i), v[i]);
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
8 / 20
Apuntadores y arreglos
Apuntadores y arreglos II
Lo que ocurre es que en C al evaluarse v [i] se convierte
inmediatamente a *(v+i).
Sin embargo existe una diferencia entre el nombre de un arreglo y
el de un apuntador.
Las instrucciones pv = v y pv++ es válida para el ejemplo
mencionado.
Las instrucciones v = pv y v++ son ilegales.
Los parámetros formales:
char s[], char *s;
en la definición de una función son equivalentes pero el último
indica más explı́citamente que el parámetro es un apuntador.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
9 / 20
Apuntadores y arreglos
Apuntadores y arreglos III
También es posible pasar a una función una posición de inicio
diferente para el arreglo como:
f (&a[2]) o bien f (a + 2)
La declaración de parámetros puede ser:
f (int a[]){. . . } o bien f (int ∗ a){. . . }
A la función f no le interesa que a sea en realidad un arreglo más
grande.
Esto permite que se puedan hacer referencias hacia atrás sobre
un arreglo siempre que las localidades sean válidas.
a[−1], a[−2]
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
10 / 20
Apuntadores y arreglos
Apuntadores y arreglos IV
Un apuntador p es incomparable a un int salvo en el caso del cero
que comúnmente se suele utilizar como la macro NULL definida
en <stdio.h>.
La instrucción p + + permite apuntar al elemento de adelante
mientras que p+ = i al que se encuentra i posiciones adelante si
i > 0.
El número de posiciones que se avanza es siempre escalado al
tamaño de a lo que apunta p, por ejemplo 1 para char o 4 si se
trata de int de 4.
Dos apuntadores pueden ser restados, por ejemplo con la
finalidad de conocer el tamaño de un arreglo.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
11 / 20
Apuntadores y arreglos
Apuntadores y arreglos V
Ejemplo: regresar la longitud de una cadena
int strlen(char *s){
char *p = s;
while(*p != ‘\0’)
p++;
return p - s;
}
No es legal sumar dos apuntadores, multiplicarlos o dividirlos,
enmascararlos o agregarles un float o un double.
Tampoco se pueden asignar dos apuntadores de diferente tipo a
menos que haya una conversión forzosa de tipo.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
12 / 20
Apuntadores a caracteres
Apuntadores a caracteres
1
Apuntadores y direcciones
2
Apuntadores y arreglos
3
Apuntadores a caracteres
4
Arreglos de apuntadores y multidimensionales
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
13 / 20
Apuntadores a caracteres
Apuntadores a caracteres I
Una constante de cadena es un arreglo de caracteres.
“Soy una cadena”
Internamente dicha cadena termina con ‘\0’.
Las cadenas constantes pueden ser tratadas como const char, sin
embargo, si tratan de ser manipuladas entonces el
comportamiento no está definido.
char amensaje[] = “hola mundo”;
char *pmensaje = “hola mundo”;/*instrucción obsoleta*/
const char *cpmensaje = “hola mundo”;
amensaje es un arreglo y dado que tiene memoria asignada
puede ser modificado.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
14 / 20
Apuntadores a caracteres
Apuntadores a caracteres II
pmensaje es una instrucción obsoleta y tratar de modificar la
cadena da un comportamiento indefinido. Sin embargo, se le
puede apuntar a otro lado.
cpmensaje es una constante de cadena y no puede ser
modificada.
Si se desea copiar una cadena t en otra s debe hacerse caracter
por caracter.
void copia(char *s, char *t){
int i = 0;
while((s[i] = t[i]) ! = ‘\0’)
i++;
return;
}
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
15 / 20
Apuntadores a caracteres
Apuntadores a caracteres III
La misma función se puede hacer simplemente manipulando los
apuntadores y a lo que apuntan.
void copia(char *s, char *t){
while((*s = *t) ! = ‘\0’)
s++, t++;
return;
}
Ejercicio: Intente reducir el tamaño de copia para lograr el mismo
propósito.
Los operadores ++ y – pueden ser utilizados en combinación con
el operador unario ∗.
*p++;/*devuelve a lo que apunta p y luego incrementa p*/
*–p;/*decrementa p y luego devuelve a lo que apunta*/
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
16 / 20
Arreglos de apuntadores y multidimensionales
Arreglos de apuntadores y multidimensionales
1
Apuntadores y direcciones
2
Apuntadores y arreglos
3
Apuntadores a caracteres
4
Arreglos de apuntadores y multidimensionales
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
17 / 20
Arreglos de apuntadores y multidimensionales
Arreglos de apuntadores y multidimensionales I
Si se desea tener un conjunto de palabras o lı́neas de texto
almacenadas en C entonces se puede utilizar un apuntador a
apuntadores.
char **lineas;/*es un apuntador a apuntadores*/
char *lineas[1000];/*son 1000 apuntadores a caracteres*/
En el caso de **lineas primero tendrı́a que apartarse memoria
para el número de apuntadores deseados y posteriormente para
cada apuntador.
La función void *malloc(size t size) permite apartar memoria para
un apuntador por lo que la siguiente instrucción da el espacio
para los 1000 apuntadores y luego para cada apuntador.
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
18 / 20
Arreglos de apuntadores y multidimensionales
Arreglos de apuntadores y multidimensionales II
lineas = (char**)malloc(1000*sizeof(char*));
for(i = 0; i < 1000; i++)
lineas[i] = (char*)malloc(MAXTAM*sizeof(char));
Como lineas es el nombre de un arreglo entonces puede tratarse
como apuntador. Lo mismo en el caso donde es un apuntador a
apuntador.
int escribir lineas(char *lineas[], int nlineas){
while(nlineas– > 0)
printf(“ %s”, *lineas++);
return;
}
Una forma de inicializar los arreglos de apuntadores a cadenas es
la siguiente:
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
19 / 20
Arreglos de apuntadores y multidimensionales
Arreglos de apuntadores y multidimensionales III
const char *mes(int n){
static const char *nombre[] = {“mes invalido”, “enero”, . . . };
return n < 1||n > 12 ? nombre[0] : nombre[n];
}
Los apuntadores a otros tipos de datos deben inicializarse con
malloc, por ejemplo:
int *v = {0, 1, 2, 3};
es una instrucción invalida. Tendrı́a que ser:
v = (int*)malloc(4*sizeof(int));
v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4;
Sergio Luis Pérez (UAM C UAJIMALPA)
Curso de Lenguaje C
20 / 20
Descargar