Lenguaje C
Apuntadores (punteros - pointers en ingls)
Variables y Memoria
La memoria del computador es como una largusima lnea (1 dimensin) en la que se guardan pulsos (dgitos 0 y 1), all solo se puede
avanzar para adelante y para atrs; lo cual es muy limitado para guardar datos del mundo real: nmeros, caracteres, dibujos, sonidos,
imgenes, video, etc. Para ello se clasifica la memoria en segmentos:
tipo 1 tipo 2 tipo 3
Cada tipo de segmento pueden interpretarse como nmeros, caracteres, imgenes, etc. A veces un tipo de segmento tiene varias
interpretaciones, por ejemplo, un segmento que contenga 1000001 puede ser interpretado como 65 10 o como 4116 o como la letra A; para
hacer esto, solo escribimos :
int n = 65;
Memoria RAM n
...01011 1000001 01100..
0x7ff...c (direccin de n en base hexadecimal)
En la realidad solo existen los nmeros 0 y 1; las indicaciones en rojo sirven para darnos informacin que nos ayuda a comprender
En tiempo de ejecucin, el sistema operativo, ubica a n en una posicin disponible, por ejemplo, 0x7ff...c. De corrida en corrida, es casi
seguro que esta posicin cambie. El programador no maneja esas posiciones, hasta ahora no ha sido importante; pero pronto veremos
aplicaciones muy importantes del manejo (indirecto) de las posiciones.
Preparemos las herramientas: Ya hemos utilizado en modo limitado dos operadores:
Operador &: suministra la direccin de una variable, por ejemplo:
printf(%p\n, &n);
Salida: 0x7ff...c
Operador *: suministra el contenido de una direccin, por ejemplo:
printf(%d\n, *&n);
Salida: 65
En resumen:
Operador Descripcin
& Operador de direccin (referencia) : &n = direccin de n = 0x7ff...c
* Operador de indireccin (dereferencia): *&n = valor de la direccin de n = 65
* es casi el inverso de &: *&n = *(&n) = n; pero &*n no compila.
Apuntador
Un apuntador ptr es una variable, como cualquier otra, diseada para guardar la direccin de otra variable, ejemplo, dada una variable:
int n = 65;
Podemos guardar en ptr la posicin de n:
ptr = &n;
Como de costumbre, podramos definir y asignar valor a la variable ptr as:
puntero ptr = &n;
Para mayor precisin, debemos indicar que ptr guarda direcciones de variables de tipo int; entonces podramos precisar:
int puntero ptr = &n;
Lo mismo sucedera para otros tipos de variables, ejemplo:
float datoFloat;
float puntero ptrf = &datoFloat; // para cada tipo de dato se tendra un puntero
En la prctica estamos creando duplicando los tipos de datos:
int puntero ptr;
float puntero ptrf;
..
PGINA: 1
Lenguaje C
Resulta exagerado duplicar el nmero de tipos de variables, por culpa de los apuntadores; veamos un artificio que nos da una solucin
corta y elegante. Tenemos una definicin:
int n;
int puntero ptr = &n;
Si aplicamos el operador * a ptr, podemos escribir:
int n;
int *ptr = &n; // *ptr es el valor apuntado por ptr
Se lee as:
El valor apuntado por ptr es de tipo int
int *ptr = &n;
valor de ptr = direccin de n
Tambin se puede definir y asignar por separado en dos instrucciones:
int n = 65;
int *ptr;
ptr = &n; // ptr toma como valor la direccin de n
O definir todo junto:
int n = 65, *ptr = &n;
Se representa as:
memoria ptr n
0x7ff...c 65
0x7ff...0 0x7ff...c
Para otros tipos de dato, se procede en modo anlogo:
float df = 21.1, *ptrf = &df;
Podramos pensar que los apuntadores son variables hacker, malas o buenas, que toman la direccin de otras variables a las cuales les
pueden cambiarles su valor; para para bien en este caso.
Atento a los detalles
1) Para qu tanto artificio? Respuesta: Al momento de programacin trabajamos con variables, lo cual es esttico: el programador
prev (adivina) tamaos de arreglos (bloques) de datos; si se queda corto, el programa funciona mal o no funciona, si se alarga,
desperdicia memoria cara. El uso de apuntadores permite aplicar la lgica a la parte fsica en tiempo de ejecucin, lo cual es
dinmico; por ejemplo si define un puntero a un bloque de 20 elementos y se necesitan 40 ms, puede redimensionarlo a 60 con
suma facilidad; esto se aplica mucho para cadenas de caracteres; esto no se puede hacer usando arreglos. Adicionalmente, los
punteros reflejan en modo directo la naturaleza lineal de la memoria RAM.
2) Al asignar valor a ptr:
int n, m, *ptr;
ptr = &n; // ptr apunta a n (al primer byte)
ptr = &m; // ptr apunta a m (otra variable)
ptr = NULL; // ptr no apunta a nada
ptr = 0x7ff...c // No compila porque no podemos manejar directamente a la memoria, esta es tarea del sistema operativo.
n = 0x6ff...c; // No compila , adems n es de tipo entero, no hexadecimal
*ptr = 0x7ff...c; // No compila , adems *ptr es de tipo entero.
3) & y * son opuestos, pero no por completo, atento:
Son opuestos para variables apuntadoras : *&ptr = ptr = 0x7ff...c; &*ptr = ptr = 0x7ff...c
No Opuestos para variables no apuntadoras : *&n = n = 65; pero &*n, no compila, debido a que *n funciona solo si n fuera una
posicin de memoria, y no lo es.
4) Un apuntador tiene tres atributos:
tipo de dato al que apuntar : int, char, etc. (un solo tipo).
tipo : apuntador, ocupa 8 bytes, el formato de impresin es %p: printf(%p, ptr);
valor : direccin de la variable o bloque apuntado (en este caso) = 0x7ff...c
tipo dato, tipo, valor
int n = 65, *ptr = &n;
PGINA: 2
Lenguaje C
5) Variables y valores del ejemplo:
n = 65 ptr = 0x7ff...c
&n = 0x7ff...c &ptr = 0x7ff...0
*n error, n no es posicin de memoria *ptr = 65
6) Mientras ptr apunte a n:
int n = 65, *ptr = &n;
Se cumplen las siguientes relaciones:
Variables Relacin Ejemplo
&n y ptr Equivalentes Leer valor de n:
scanf(%d, &n);
scanf(%d, ptr);
No equivalentes ptr = &m; // apunta a otra variable
&n = algo; // error: no se asigna posicin de memoria a una variable
n y *ptr Equivalentes Escribir valor de n
printf(%d, n); printf(%d, *ptr);
Asignar valor cualquiera a n:
n = 65; *ptr = 65;
n += 2; *ptr += 2;
7) Un solo operador * representa a dos operaciones distintas:
* : Indireccin
* : Multiplicacin
El operador de indireccin * tiene mayor prioridad que el operador de multiplicacin *, ejemplo:
int n=2, *ptr= &n, b;
b = *ptr * 2; // es equivalente a: b = *ptr*2; b = 2 * *ptr; b = 2**ptr; b = 2 * * ptr; (no importa la cantidad de espacios)
No abuse de la escritura confusa, de ser necesario use parntesis para aclararla. Ms adelante completaremos las reglas de
priorizacin.
Ejemplo: Una variable puede ser apuntada por varios apuntadores:
p1 p2 n m
0x7ff...a 0x7ff...a 2 8
0x7ff...a
#include<stdio.h>
void main(void){
int n=2 , *p1= &n, *p2= &n, m = 8; // declaracin y asignacin de valores
if(p1==p2) printf("%d %d\n", *p1, *p2); // Igualdad de apuntadores
}
Salida:
2 2
Observaciones:
El valor de n puede cambiar de 3 modos:
n = 4;
*p1 = 4;
*p2 = 4;
Un puntero apunta a 0 o 1 variable; pero puede cambiar de variable apuntada:
p1 = &m; // y deja de apuntar a n
Apuntador constante
int a=10, b=20;
int * const p = &a; // p apunta solo a la variable a.
*p = 15; // Correcto: asigna 15 a a, el valor apuntado es variable.
p=&b; // ERROR: El valor de p es constante
p a b
0x7ff...a 15 20
0x7ff...a
PGINA: 3
Lenguaje C
Ya utilizamos apuntadores en funciones para pasar valores por referencia:
miFun(&n); // el valor de n cambiar a 3.
Llama a:
void miFun(int *n) {*n= 3;}
Pero el uso ms frecuente es para apuntar a bloques de datos, como veremos a continuacin.
Arreglo de una dimensin
Un arreglo es un bloque de n datos del mismo tipo almacenados en modo consecutivo, ejemplo:
int arr[3] = {10, 20, 30};
arr
10 20 30
0x7ff...a
Indices: 0 1 2
Un arreglo de una dimensin es ideal para ser controlado por un apuntador; de hecho, un arreglo arr se comporta como un puntero
constante que apunta a su primer elemento:
arr == &arr[0] // arr apunta a su primer elemento.
*arr == arr[0] // 10
En modo general se cumple:
Notacin vectorial Notacin de punteros Valor
arr; 0x7ff...a
arr[0]; *(arr+0); *arr; 10
arr[1]; *(arr+1); 20
arr[2]; *(arr+2); 30
arr[1] = 80; *(arr+1) = 80; 80
n = fun(arr, 3); n = fun(arr, 3); Llama a la funcin fun()
int fun(int arr[ ], int n){ int fun(int *arr, int n) { Define a la funcin fun()
arr[0] = 2; *arr = 2;
arr[1] = 3; *(arr+1) = 3;
*(arr+2) = 4; arr[2] = 4;
} }
Ejemplo: Imprimir los elementos de un arreglo utilizando notacin vectorial y de apuntadores:
Programa 06_01a.c:
#include<stdio.h>
void main(void){
int arr[3] = {6, 5 , 4}, i;
for(i=2; i>=0; i--) printf("%d %d\n", arr[i], *(arr+i)); // Notacin de apuntadores
}
Salida:
4 4
5 5
6 6
El mismo ejemplo llamando a una funcin
Programa 06_01b.c:
#include<stdio.h>
void imprimir(int arr[], int n);
void main(void){
int arr[3] = {6, 5 , 4};
imprimir(arr, 3);
}
void imprimir(int arr[ ], int n) {
int i;
for(i=n; i>=0; i--) printf("%d %d\n", arr[i], *(arr+i)); // Notacin de apuntadores
}
Salida: la misma del problema anterior
PGINA: 4
Lenguaje C
Apuntador a arreglo de una dimensin
Un arreglo se comporta como un apuntador constante, lo cual imposibilita que cambie la posicin apuntada (a su primer elemento), un
apuntador que apunta al arreglo no tendra esta limitante, ejemplo:
int arr[3] = {10, 20 ,30}, arr1[4], *ptr;
ptr = arr; // no es necesario & ya que arr es un puntero (constante)
ptr = arr1;
arr = arr1; // Error de compilacin
memoria ptr arr arr1
0x7ff...0 10 20 30
0x7fa...b 0x7ff...0
Aritmtica de punteros
Dada la naturaleza de un puntero -apunta a una direccin sobre una lnea-, el puntero se puede desplazar a la derecha-izquierda,
mediante sumas y restas:
ptr = ptr + 1; // ptr apunta a la siguiente posicin de tipo int: avanza 4 bytes: 0x7ff...4
// si ptr apuntara a un tipo long, sumar 8 bytes, para char sumar 1 byte; etc.
ptr = ptr + n; // equivalente a ptr += n;
ptr = ptr - n; // equivalente a ptr -= n;
ptr + 2*3+1; // = pptr + 7; apunta 7 posiciones de bytes, es decir 7*4 bytes ms adelante.
Se permite la resta de dos punteros:
int nn[10], *ptr1, *ptr2, n;
ptr1 = nn; // equivalente a: ptr1 = &nn[0];
// apunta a nn[0].
ptr2 = &nn[2]; // apunta a nn[2].
n = ptr2 ptr1; // diferencia en posiciones enteras = 2.
No se permiten otro tipo de operaciones
ptr = ptr * 2; // Error: No se admiten multiplicaciones de valores de memoria
ptr1 = ptr1 + ptr2; // Error
Mientras ptr apunte a arr:
int arr[3] = {10, 20, 30}, *ptr = arr;
Son equivalentes (sinnimos) por completo
arr[i] = = ptr[i];
*(arr+i) = = *(ptr+i);
Pre y postoperadores, funcionan como siempre:
arr++; // error porque arr es puntero constante
ptr++; // aumenta 1 a ptr;
printf("%p\n", ptr++); // printf("%p\n", ptr); ptr++;
printf("%p\n", (ptr+1)++); // error de compilacin, no se puede postoperar a una expresin (ptr+1)
*arr++; // error porque arr es puntero constante
*ptr++;
printf("%d\n", *ptr++); // printf("%d\n", *ptr); ptr++;
printf("%d\n",*(ptr++)); // printf("%d\n", *ptr); ptr++;
printf("%d\n", *(ptr+1)++); // error de compilacin
++arr; // error porque arr es puntero constante
++ptr; // aumenta 1 a ptr;
printf("%p\n", ++ptr); // ++ptr; printf("%p\n", ptr);
printf("%p\n", ++(ptr+1)); // error de compilacin
*arr++; // error porque arr es puntero constante
++*ptr; // aumenta 1 a *ptr;
printf("%d\n", ++*ptr); // aumenta 1 a *ptr; printf("%d\n", *ptr) ;
printf("%d\n",++(*ptr)); // aumenta 1 a *ptr; printf("%d\n", *ptr) ;
printf("%d\n", ++*(ptr+1)); // aumenta 1 a *(ptr+1); printf("%d\n", *(ptr+1));
PGINA: 5
Lenguaje C
Arreglo de dos dimensiones
Podemos visualizar con facilidad una matriz, basta representarla en un papel (dos dimensiones):
2 4 6 7
8 10 12 14
La memoria del computador es de una sola dimensin, no queda otra alternativa que adaptar las dos dimensiones a una:
int arr[2][4] = {2, 4, 6, 7, 8, 10, 12, 14};
Posicin[]: 0 1 2 3 4 5 6 7
Posicin[ ][ ]: arr[0][0] arr[0][1] arr[0][2] arr[0][3] arr[1][0] arr[1][1] arr[1][2] arr[1][3]
Valores 2 4 6 7 8 10 12 14
0X7234... = posicin fsica
Analizando las posiciones lineales y matriciales anteriores, deducimos que:
arr[i][j] ocupa la posicin i*4+j en la memoria
En general. para un arreglo arr[m][n], el elemento arr[i][j] ocupa la posicin: i*n+j en la memoria.
Los arreglos de dos dimensiones nos ayudan pero presentan tres limitaciones:
El lenguaje C los concibe como un arreglo de arreglos
arr[0]: fila 0 // arr[0][0] 2 arr[0][1] 4 arr[0][2] 6 arr[0][3] 7
arr[1]: fila 1 // arr[1][0] 8 arr[1][1] 10 arr[1][2] 12 arr[1][3] 14
Esta solucin no es unidimensional y presentar inconvenientes ms adelante.
Se debe estimar el nmero de fila y columnas por exceso, lo cual es un gran desperdicio de memoria, por otra parte si nos
excedemos, no hay advertencia de ello, y nos esperan errores y/o el aborto del programa.
Al pasar arreglos a funciones se pierde flexibilizad a partir de la segunda dimensin.
Afortunadamente, se resuelven los tres problemas anteriores en modo ptimo: Trabajar con punteros, asignar memoria dinmicamente y
controlar el nmero de elementos en cada dimensin; lo cual haremos en dos captulos ms adelante; por el momento hagamos una
aproximacin conceptual trabajando con arreglos y apuntadores:
Apuntador a arreglo de dos dimensiones
int arr[2][3] = {2, 4, 6, 8, 10, 12}, *ptr = arr; // no se requiere &. ptr y arr apuntan a la misma direccin.
Posiciones: 0 1 2 3 4 5
ptr arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
0x7234 2 4 6 8 10 12
0x7234...
arr[i][j] es equivalente a *(ptr+ i*3+j)
En general para: int arr[m][n];
arr[i][j] ocupa la posicin: i*n+j.
arr[i][j] es equivalente a *(ptr+ i*n+j)
La notacin de punteros es engorrosa para referirse a los elementos de un arreglo; pero su uso permite parametrizar las dimensiones.
Paso de argumentos a funcin
Paso de una variable
Ejemplo: Calcular la mitad de un nmero
Programa 06_02a.c:
Paso de variable por valor Paso de variable por referencia Paso de puntero a variable
#include <stdio.h> #include <stdio.h> #include <stdio.h>
void mitad(int n); // prototipo void mitad(int *n); // prototipo void mitad(int *pn); // prototipo
void main(void){ void main(void){ void main(void){
int n = 2; int n = 2; int n = 2, *pn = &n;
mitad(n); // llamando mitad(&n); // llamando mitad(pn); // llamando
PGINA: 6
Lenguaje C
printf("n = %d\n", n); printf("n = %d\n", n); printf("n = %d\n", n);
} } }
void mitad(int n){ // funcin void mitad(int *n){ // funcin void mitad(int *pn){ // funcin
n /=2; *n /=2; *pn /=2;
} } }
Salida: n = 2 Salida: n = 1; Salida: n = 1;
Paso de puntero a arreglo
Ejemplo: Calcular la mitad de los elementos
Programa 06_02b.c:
Usando punteros Sin usar punteros
1 dimensin 2 dimensiones
#include <stdio.h> 01 #include <stdio.h> #include <stdio.h>
void mitad(int *parr, int n); 02 void mitad(int *parr, int m, int n); void mitad(int parr[][2], int m, int n);
void main(void){ 03 void main(void){ void main(void){
int arr[4] = {1, 2, 3, 4}, *parr = arr, i; 04 int arr[2][2] = {1, 2, 3, 4}, *parr = arr, i, j; int arr[2][2] = {1, 2, 3, 4}, i, j;
mitad(parr, 4); 05 mitad(parr, 2, 2); mitad(arr, 2, 2);
for(i=0; i < 4; i++) 06 for(i=0; i < 2; i++) for(i=0; i < 2; i++)
printf("%d\t", arr[i]); 07 for(j=0; j < 2; j++) printf("%d\t", arr[i][j]); for(j=0; j < 2; j++) printf("%d\t", arr[i][j]);
} 08 } }
void mitad(int *parr, int n){ 09 void mitad(int *parr, int m, int n){ void mitad(int arr[][2], int m, int n){
int i; 10 int i, j; int i, j;
11 for(i=0; i < m; i++) for(i=0; i < m; i++)
for(i=0; i < n; i++) *(parr+i) /=2; 12 for(j=0; j < n; j++) *(parr+i*n+j) /=2; for(j=0; j < n; j++) arr[i][j] /=2;
} 13 } }
Salida: 0 1 1 2 Salida: 0 1 1 2 Salida: 0 1 1 2
Nota: 1 Nota: 2 Nota: 3
Notas:
1: El programa es paramtrico en una dimensin.
2: El programa es paramtrico en las dos dimensiones; pero compila con un warning (advertencia) por tipo de apuntador en la lnea 04,
debido a que un apuntador de tipo int (lineal) apunta a una matriz (arreglo de arreglos) de tipo int; pero ejecuta bien (por que
controlamos las dimensiones). El programa compilar limpiamente cuando usemos solo punteros y memoria dinmica, que ser dos
captulos ms adelante.
3: El programa es paramtrico solo en la primera dimensin, ms no en la segunda.
Ejercicio: Definir un arreglo, calcular el mnimo, la suma y la media
Veamos dos temas que usaremos ms adelante.
Arreglo de apuntadores
Un puntero es una variable como cualquier otra, por lo tanto podemos tener arreglos de punteros, ejemplo:
int *ptr[4], n = 6;
ptr[1] = &n;
*ptr[1]; // = 6
ptr n
0xff..c 6
Posiciones 0 1 2 3 0xff..c
Apuntador a apuntador
Un puntero es una variable como cualquier otra, por lo tanto podemos definir un puntero a puntero:
Sintaxis: tipo **nombreApuntador, ejemplo:
int a = 3, *b = &a, **c = &b;
c b a
0x7234.. 0x8174.. 3
0x65734.. 0x7234.. 0x8174..
printf("%d\n", a); // resultado: 3
PGINA: 7
Lenguaje C
printf("%d\n", *b); // resultado: 3
printf("%d\n", **c); // resultado: 3
a = 4; // es equivalente a: *b = 4; **c = 4;
Atento: el operador * tiene diferentes usos:
Uso
* Para indicar puntero: *p1
** Para indicar puntero a puntero: int **p2
* Operador de multiplicacin: a * b
Expresin 2 ***p2; // es vlida y el compilador la reconoce, pero ud. se puede confundir, no abuse, use parntesis para separar.
Ejemplo: Definir, asignar valores y representar la memoria fsica:
int arr[4] = {15, 13, 11, 9}, *ptr1, **ptr2;
ptr1 = arr; ptr2 = *ptr1;
La implantacin en memoria sera:
ptr2 ptr1 arr
0x7234.. 0x8174.. 15 13 11 9
0x65734.. 0x7234.. 0x8174..
int arr[4] = {15, 13, 11, 9}, *ptr1, **ptr2;
ptr1 = arr; ptr2 = &ptr1;
printf("%d\n", *arr); // resultado: 15
printf("%d\n", *ptr1); // resultado: 15
printf("%d\n", **ptr2); // resultado: 15
Reglas de priorizacin de los modificadores *, ( ) y [ ]
1) La cercana (derecha o izquierda) al puntero
2) ( ) y [ ] tienen mayor prioridad que *
3) Use parntesis para dar mayor prioridad, como en: (3 + 4) * 2
Ejemplo:
int *ptr[2][3];
* y [2] son adyacentes a ptr, y tienen mayor prioridad que [3] (regla 1):
(*ptr[2])[3] [2] tiene preferencia sobre * (regla 2)
*(ptr es un arreglo de 2 elementos)[3] [3] tiene preferencia sobre * (regla 2)
*(ptr es un arreglo de [2][3] elementos) ptr es un arreglo de [2][3] elementos de punteros a int
ptr j m n
2 6 4
Programa 06_03.c:
#include<stdio.h>
void main(void){
int *ptr[2][3], j= 2, m=6, n=4;
ptr[0][0] = &j;
ptr[0][1] = &m;
ptr[0][2] = &n;
printf("%d\n", *ptr[0][0]);
printf("%d\n", *ptr[0][1]);
printf("%d\n", *ptr[0][2]);
}
Salida:
2
6
4
ejemplo:
int (*ptr)[2][3];
(*ptr) Es un puntero
(*ptr)[2][3] Es un puntero a arreglos [2][3] de tipo int
PGINA: 8
Lenguaje C
Ejemplo:
int aa[2][3] = {1,2,3,4,5,6};
int *ptr = aa;
ptr aa
1 2 3 4 5 6
Estas reglas se aplican tambin para funciones:
int *miFun(); // miFun() retorna un puntero a int
int miFun(int *ptr); // El parmetro de miFun() es de tipo puntero a int
Apuntador a void
La palabra reservada void (se pronuncia void en ingls y significa vaco, nulo, vacante, ...) se utiliza para crear un puntero sin especificar
el tipo de dato al que apuntar:
int in=1;
double db=2.4;
void *pvoid; // un apuntador a void puede apuntar a cualquier tipo de dato:
pvoid = ∈ int *pin = (int *)pvoid; printf("%d\n", *pin); // = 1
pvoid = &db; double *pdb = (double *)pvoid; printf("%lf\n", *pdb); // = 2.4
pin pdb pvoid in db
1 2.4
Ejemplo: La funcin free( ) usa este parmetro:
void free(void *ptr); // free acepta un puntero a cualquier tipo de dato y le quita la referencia, lo hace NULL.
Ventajas, desventajas y usos de apuntadores
Ventajas Permiten adaptarse a la memoria lineal del computador.
Ahorran memoria, los arreglos desperdician mucha memoria.
Permiten parametrizar la entrada a funciones con arreglos multidimensionales.
Desventajas La notacin de punteros es un poco ms compleja.
Pueden ser un poco ms lentos de ejecutar que con arreglos simples. Ya que esta parte es optimizada por C, mientras
que los punteros los maneja el programador.
Usos Se usa preferentemente para manejar bloques de memoria, recuerde las limitaciones para pasar arreglos de ms de
una dimensin a funciones, ahora eso no ser un problema.
No se suele apuntar a variables simples
Ejemplo: Dado un puntero como, float *fp. Verifique que al sumar n a fp (fp += n); la direccin apuntada por fp aumenta a:
n*sizeof(float).
Programa 06_04.c:
#include<stdio.h>
void main(void){
float f, *fp = &f;
long int d1, d2;
int n=2;
printf("\nPrimera direccin apuntada: %p (en hexadecimal)\n", fp);
d1 = (long int)fp; // primera direccin apuntada
fp +=n;
d2 = (long int)fp; // segunda direccin apuntada
printf("Segunda direccin apuntada: %p (fp + 2)\n", fp);
printf(" --------------\n");
printf("Aumento de direccin : %lu\n", d2 - d1);
printf("n*sizeof(float) = %d * %lu = : %lu\n", n, sizeof(float), n*sizeof(float));
}
Salida:
Primera direccin apuntada : 0x7fff329c5ee0 (en hexadecimal)
Segunda direccin apuntada: 0x7fff329c5ee8 (fp + 2)
-------------------
PGINA: 9
Lenguaje C
Aumento de direccin : 8
n*sizeof(float) = 2 * 4 = : 8
Apuntaste bien!!!!
Origen: [Link]
Has aprendido un tipo de variable muy importante, potente y peligrosa (puedes cometer el famoso error: violacin de segmento, que es
difcil de corregir). Con ella abandonars tu mundo virtual (lo que pareca ser un programa) y te internars en la realidad (la estructura de
la RAM). No es tan difcil dominar los apuntadores: Toda la teora est bien organizada y completa; te recomiendo: 1) Enamrate del
tema, 2) Haz una sesin personal especial y trata de entender todos los detalles, 3) Renete con los amigos para ir de cacera, perdn
para resolver problemas. Ya casi eres un profesional. Ahh!, centale a tu novi@ para que no se ponga celos@.
Ejercicios:
1) Para un arreglo tridimensional, por ejemplo:
int a[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} ;
Que posicin lineal ocupar a[i][j][k]?
2) Una matriz p[4][12] representa una produccin de los 12 meses en 4 aos. Lea la matriz y use punteros para calcular el promedio de
produccin en cada ao y en los 12 meses:
Aos
1 2 3 4
Promedio: xx xx xx xx
Meses
1 2 3 4 12
Promedio: xx xx xx xx xx
PGINA: 10