CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
DOCUMENTE SIMILARE |
|
PUNTEROS EN C
1.- INTRODUCCIÓN
Un puntero es una variable que representa la dirección en memoria de otro dato.
Supongamos que v es una variable que representa un dato determinado. El compilador automáticamente asignará celdas de memoria para este dato. El dato puede ser accedido si conocemos la dirección de la primera celda de memoria (ya que celdas adyacentes están numeradas consecutivamente).
La dirección de memoria de v puede ser determinada mediante la expresión &v, donde & es un operador unario, llamado operador dirección, que proporciona la dirección del operando (sólo se puede aplicar a variables y elementos de arrays). Si asignamos la dirección de v a otra variable pv, esta nueva variable es un puntero a v.
Además, el dato representado por v puede ser accedido mediante la expresión *pv, donde * es un operador unario llamado operador indirección (sólo se puede aplicar a punteros).
Ej: int u=3;
int v;
int *pu; /* puntero a entero */
int *pv; /* puntero a entero */
pu= &u; /* asigna la dirección de u a pu. Por tanto, pu es un puntero a u */
v= *pu + 1; /* asigna a v el valor de u más 1 */
pv= &v /* asigna la dirección de v a pv */
Los valores de cada variable serían:
u=3 &u=F8E pu=F8E *pu=3
v=4 &v=F8C pv=F8C *pv=4
Las variables puntero pueden apuntar a variables numéricas o de caracteres, arrays, funciones, variables puntero y otras estructuras de datos que veremos posteriormente.
2.- DECLARACIÓN DE PUNTEROS
Cuando una variable puntero es definida, el nombre de la variable debe ir precedido por un asterisco (*). El tipo de dato que aparece en la declaración se refiere al tipo de dato del objeto al que apunta el puntero. La forma es:
tipo_dato *ptvar;
Una variable puntero puede ser inicializada en su declaración, asignándole la dirección de otra variable que debe estar previamente declarada. Hay una situación especial de asignación en la cual se puede asignar el entero 0 a un puntero. En este caso es recomendable definir una constante simbólica NULL que represente el valor 0.
Ej: #define NULL 0
float u,v;
float *pv = &v;
float *pu = NULL;
3.- PASO DE PUNTEROS A UNA FUNCIÓN
Muchas veces los punteros se pasan a las funciones como argumentos. Esto permite que datos de la porción de programa donde se llama la función sean accedidos por la función, alterados dentro de ella y luego devueltos al programa de forma alterada. A este uso de los punteros se denomina pasar argumentos por referencia. Por contra, cuando un argumento es pasado por valor, el dato es 'copiado' a la función y las modificaciones hechas dentro de la misma no permanecen después de salir.
Los argumentos formales de una función que sean punteros deben ir precedidos por un asterisco (*). Lo mismo ocurre en la declaración de prototipos de funciones.
Ej: main()
void func1(int u, int v)
void func2(int *pu, int *ppv)
Después de salir de func1, u y v siguen valiendo 1 y 3, respectivamente.
Después de salir de func2, u y v valen 0.
Un array que aparece como argumento formal en la definición de una función puede ser declarado como un puntero o como un array de tamaÑo no especificado.
Ej: char linea[80];
void imprime_linea (char linea[]) o bien void imprime_linea (char *linea)
4.- PUNTEROS Y ARRAYS UNIDIMENSIONALES
Recordar que el nombre de un array es un puntero al primer elemento de ese array. Si este array es unidimensional, la dirección del primer elemento puede ser expresada como &x[0] o simplemente x. Además, la dirección del segundo elemento se puede escribir tanto &x[1] como (x+1), y así sucesivamente. En general, la dirección del elemento i del array se puede expresar como &x[i] o como (x+i).
De forma análoga, x[i] y *(x+i) representan el contenido de la posición i-ésima del array.
Ej: main()
;
int *pi;
*x= 20; /* correcto */
x[1]= 21; /* correcto */
*(x+2)= 22; /* correcto */
pi= &x[2]; /* correcto */
x[3]= *pi+1; /* correcto */
&x[1]= &x[2]; /* incorrecto */
(x+5)= &x[2]; /* incorrecto */
++x; /* incorrecto */
}
Al final tendremos:
x[0]=20 x[1]=21 x[2]=22 x[3]=23 el resto igual.
Ya sabemos que el nombre de un array es, en realidad, un puntero al primer elemento de este array. Por tanto, es posible definir un array como una variable puntero en vez de como un array convencional (pero no se pueden asignar valores iniciales).
Ej: int *x; en vez de int x[10];
Sin embargo, la definición convencional del array produce la reserva de un bloque fijo de memoria al inicio de la ejecución del programa, cosa que no ocurre si la definición es en forma de variable puntero. En este último caso, hay que reservar el espacio necesario en memoria antes de procesar los elementos del array (generalmente con la función de biblioteca malloc).
Ej: x = (int *) malloc (10 * sizeof (int) ); /* Notar que la dimensión puede */
x = (int *) malloc (20 * sizeof (int) ); /* ser cualquiera (no siempre 10) */
5.- OPERACIONES CON PUNTEROS
Un valor entero puede ser sumado o restado a una variable puntero, pero el resultado de la operación debe ser interpretado con cuidado. Si tenemos la variable puntero px que representa la dirección de una variable x. Podemos escribir expresiones como --px, ++px, (px+3). Cada expresión representa una dirección localizada a cierta distancia de la posición original representada por px. La distancia exacta será el producto de la cantidad entera por el número de bytes o palabras que ocupa cada elemento del tipo al que apunta px. Sin embargo, la nueva dirección no tiene porqué ser una dirección de otro elemento.
Ej: int *px;
px 2 bytes |
(px+3)
char *py;
py 1 byte |
(py+3)
Una variable puntero puede ser restada de otra siempre que ambas variables apunten a elementos del mismo array. El resultado indica el número de palabras o bytes que separan los correspondientes elementos del array.
Ej: int a[6]=;
int *px, *py;
px=&a[0];
py=&a[5];
Daría py-px=5;
Las variables puntero pueden ser comparadas siempre que apunten al mismo tipo de dato. Esto puede ser útil cuando ambas variables apunten a elementos del mismo array. Además una variable puntero puede ser comparada con 0 (normalmente expresado como NULL).
En resumen, las operaciones permitidas con punteros son:
A una variable puntero se le puede asignar la dirección de una variable ordinaria: (pv=&v)
A una variable puntero se le puede asignar el valor de otra variable puntero, siempre que ambos apunten al mismo tipo de datos: (px = py)
A una variable puntero se le puede asignar un valor nulo (cero ó NULL).
Una cantidad entera puede ser sumada o restada a una variable puntero.
Una variable puntero puede ser restada de otra si ambas apuntan a elementos del mismo array.
Dos variables puntero puede ser comparadas si ambas apuntan a datos del mismo tipo.
6.- PASO DE FUNCIONES A OTRAS FUNCIONES
Cuando una función acepta el nombre de otra como argumento, la declaración formal debe identificar este argumento como un puntero a otra función. En su forma más simple, un argumento formal que es un puntero a función puede declararse como:
tipo_dato (*nombre_función) ( );
donde tipo_dato es el tipo de dato del valor devuelto por la función. Esta función puede accederse por medio del operador de indirección de la siguiente forma:
(*nombre_función) (argumento1, argumento2, , argumentoN);
El prototipo de una función que acepta un puntero a otra función como argumento se puede escribir:
tipo_dato_función nombre_función(tipo_dato_arg (*) (tipo1, tipo2, ),
tipos_de_otros_argumentos);
o bien:
tipo_dato_función nombre_función
(tipo_dato_arg (*pt_var) (tipo1 arg1, tipo2 arg2, ),
tipos_de_otros_argumentos);
Ej: main( )
int proceso(pf) /* definición de función */
int (*pf) ( ); /* declaración de arg. formal (puntero a función) */
int func1(a, b) /* definición de función */
int a, b;
int func2(x, y) /* definición de función */
int x, y;
Ej: Cambiando la forma de definir los argumentos de las funciones.
main( )
int proceso(int (*pf) (int, int)) /* definición de función */
int func1(int a, int b) /* definición de función */
int func2(int x, int y) /* definición de función */
7.- MÁS SOBRE DECLARACIONES DE PUNTEROS
Las declaraciones de punteros pueden volverse muy complicadas, sobre todo si contienen referencias a funciones o arrays. Además, los paréntesis se pueden usar para indicar funciones o para establecer precedencias.
Ej: int *p (int a); p es una función que acepta un argumento entero y
devuelve un puntero a un entero.
int (*p)(int a); p es un puntero a una función que acepta un argumento
entero y devuelve un entero.
int *(*p)(char *a[]); p es un puntero a una función que acepta un argumento
que es un array de punteros a carácter y devuelve
un puntero a entero.
int (*p)(char (*a)[]); p es un puntero a una función que acepta un argumento
que es un puntero a un array de caracteres y retorna
un entero.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 692
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved