PDF de programación - Punteros en ANSI C

Imágen de pdf Punteros en ANSI C

Punteros en ANSI Cgráfica de visualizaciones

Actualizado el 23 de Febrero del 2020 (Publicado el 14 de Enero del 2017)
1.538 visualizaciones desde el 14 de Enero del 2017
712,7 KB
8 paginas
Creado hace 20a (28/10/2003)
Última Revisión: 28 de octubre de 2003 ::.

Punteros en C

Escuela Superior de Informática - Ciudad Real
Universidad de Castilla-La Mancha

Carlos González Morcillo ::: [email protected]
Miguel Ángel Redondo Duque ::: [email protected]
http://www.inf-cr.uclm.es/www/cglez
http://www.inf-cr.uclm.es/www/mredondo
© 2003 Carlos González Morcillo - Miguel Ángel Redondo Duque. Se permite la copia, distribución y/o modificación de este documento bajo los términos de la
licencia de documentación libre GNU, versión 1.1 o cualquier versión posterior publicada por la Free Software Foundation; sin secciones invariantes. Puede
consultar esta licencia en http://www.gnu.org


Tabla de Contenidos

INTRODUCCIÓN ...................................................................1
¿QUÉ ES UN PUNTERO?.....................................................1
¿PARA QUÉ USAR PUNTEROS?........................................2
ARITMÉTICA DE PUNTEROS ..............................................3
CADENAS DE CARACTERES..............................................4
ESTRUCTURAS ....................................................................5
PUNTEROS A MATRICES ....................................................5
ASIGNACIÓN DINÁMICA DE MEMORIA .............................6
PUNTEROS A FUNCIONES..................................................7
¿Y AHORA QUÉ?..................................................................8



Introducción

«Díjole el perro al hueso: Si tú eres duro,
yo tengo tiempo...» Refranero Popular


S

uele resultar difícil dominar el concepto de punte-
ro. Especialmente a los programadores que
aprendieron con lenguajes de alto nivel, donde no se
permite trabajar directamente con posiciones de
memoria. El mayor problema en C surge al tratar de
detectar esos «segmentation fault» maquiavélicos
que a veces aparecen, a veces no.

Este documento pretende llenar esta laguna con un
texto breve, que introduce los fundamentos de los
punteros con numerosos ejemplos. No es posible
aprender a programar únicamente leyendo un docu-
mento, así que aplicando el «Caminante no hay
camino, se hace camino al andar», utiliza un compila-
dor ANSI C y compila, prueba y cambia los ejemplos
de esta guía. Si únicamente lees el texto, no cogerás
manejo y tu lectura valdrá para poco.

Miles de agradecimientos a nuestros compañeros
Miguel Ángel Laguna, Ramón Manjavacas y David
Villa por aportar ideas y depurar este documento.

Será bienvenida cualquier indicación acerca de este
texto, errores encontrados, dudas y aclaraciones en
nuestra cuenta de e-mail.

¿Qué es un puntero?

En el famoso libro de Kernighan y Ritchie “El lenguaje
de programación C”, se define un puntero como «una
variable que contiene la dirección de una variable».
Tras esta definición clara y precisa, podemos remar-
car que un puntero es un tipo especial de variable
que almacena el valor de una dirección de memoria.

La memoria de los ordenadores está formada por un
conjunto de bytes. Simplificando, cada byte tiene un
número asociado; una dirección en esa memoria.


Contenido de cada
Posición de Memoria

...
145 146 147 148 149 150 151 152 153 154

...

Direcciones de Memoria



Figura 1. Representación de la Memoria

La representación anterior se utilizará a lo largo del
texto para ilustrar los distintos ejemplos. De esta
forma, si ejecutamos el ejemplo del Listado 1:

01 #include <stdio.h>
02 int main(void)
03 {
04 float pi=3.14;
05 printf ("%.2f\n", pi);
06 return 0;
07 }

Listado 1

Obtenemos en pantalla el esperado 3.14. Sin embar-
go, ¿qué operaciones ha hecho el ordenador hasta
mostrar el resultado?. En la línea 4, la instrucción
reserva memoria para la variable pi. En este ejemplo,
asumimos que un decimal de tipo float ocupa 4 bytes.
Dependiendo de la arquitectura del computador, la
cantidad de bytes requerida para cada tipo de datos
puede variar.

La Figura 2 muestra el estado de la memoria después
de la declaración de la variable pi. La representación
elegida facilita el seguimiento de los ejemplos, sin
embargo, la representación real en la memoria de
ordenador no tendría esa disposición.

Apuntes de Punteros en ANSI C – Escuela Superior de Informática Ciudad Real (UCLM)

1.

pi

pi

dir

...
145 146 147 148 149 150 151 152 153 154

1 4

3 .

Dirección de comienzo de pi

...



Figura 2. Memoria reservada para una variable

Cuando se utiliza pi en la línea 5, ocurren dos pasos
diferenciables. En primer lugar, el programa busca la
dirección de memoria reservada para pi (en nuestro
ejemplo, sería la dirección 146). Hecho esto, en
segundo lugar, el programa recupera el contenido de
esa dirección de memoria.

Así, distinguimos por un lado la dirección de memoria
asignada a una variable, y por otro lado el contenido
de la posición de memoria reservada. Podemos
acceder a la dirección de una variable utilizando el
operador &. Mediante este operador, obtenemos la
dirección donde se almacena la variable (¡un núme-
ro!). En el ejemplo del Listado 2, se ha utilizado %u y
una conversión forzada a entero sin signo para que la
salida por pantalla sea más entendible. Se podía
haber utilizado el conversor estándar para punteros
%p y haber quitado la conversión forzada a entero sin
signo.

01 #include <stdio.h>
02 int main(void)
03 {
04 float pi=3.14;
05 printf ("Dirección de pi: %u\n",
(unsigned int)&pi);
06 return 0;
07 }

Listado 2

Si ejecutáramos el programa del listado 2 en la me-
moria del ejemplo anterior, debería mostrarnos la
dirección 146. Recordemos que una dirección de
memoria es únicamente un número. De hecho, po-
dríamos almacenarla en una variable entera sin signo
(ver Listado 3).

01 #include <stdio.h>
02 int main(void)
03 {
04
float pi=3.14;
05
unsigned int dir=(unsigned int)&pi;
06 printf ("Direcc. de pi: %u\n", dir);
07 return 0;
08 }

Listado 3

El código anterior demuestra que no hay nada de
magia ni efectos especiales en el tema de las direc-
ciones. Simplemente son números que pueden ser
almacenados en variables enteras1. Esto se puede ver
gráficamente en la siguiente figura (suponiendo que
las variables de tipo entero sin signo requieran 3
bytes en memoria).


1 Recordemos que el modificador unsigned simplemente
indica que no se permiten números negativos. Las direccio-
nes no pueden ser negativas.

...
145 146 147 148 149 150 151 152 153 154

1 4 1 4 6

3 .

dir = &pi

Figura 3. Uso del operador '&'

...



Lo que se quiere representar simplemente es que
mediante el operador & accedemos a la dirección de
memoria de una variable. Esta dirección es un simple
número entero con el que podemos trabajar directa-
mente.

Para diferenciar una variable entera que almacene
valores de nuestro programa (por ejemplo, índices,
contadores, valores...) de las variables que almace-
nan direcciones, en C se creó un nuevo tipo de varia-
ble para almacenar direcciones. Este tipo es, preci-
samente, el puntero. Así, podemos tener algunas
declaraciones de punteros como las siguientes:


char * nombre;
float * altura;


¿Cómo interpretar las líneas anteriores? Podemos leer
que nombre es un entero, pero podemos añadir que
es un entero especialmente diseñado para guardar la
dirección de un carácter. Por su parte, altura es un
entero, además es un entero especialmente diseñado
para guardar la dirección de un float. Es lo que deci-
mos resumidamente con “nombre es un puntero a
char” o “altura es un puntero a float”.

El operador * también se utiliza para recuperar el
contenido de una posición de memoria identificada
por una dirección. No debemos confundir su uso en la
declaración de un puntero, como hemos visto antes,
con los casos en que se emplea para recuperar el
contenido de una posición de memoria. Este uso lo
veremos a continuación.

¿Para qué usar punteros?

Hagamos un programa que cambie el valor de la
variable pi del ejemplo anterior a cero. Para ello,
realizaremos el código que se muestra en el Listado
4. En este caso intentamos pasar el parámetro vpi
por referencia, para que cambie el contenido de pi
dentro de la función. Si ejecutamos el programa, el
resultado obtenido no es el esperado. ¿Por qué?

01 void cambiavalor(float vpi) {
02 vpi = 0;
03 printf ("Dirección de vpi: %u\n",
(unsigned int) &vpi);
04 printf ("Valor de vpi: %f\n", vpi);
05 }
06 int main(void){
07 float pi=3.14;
08 cambiavalor(pi);
09 printf ("Dirección de pi: %u\n",
(unsigned int) &pi);
10 printf ("Valor de pi: %f\n", pi);
11 return 0;
14 }

Listado 4

.2

Carlos González Morcillo ([email protected]) ::: Miguel Ángel Redondo Duque ([email protected])

La ejecución del programa muestra que el parámetro
pi ha sido pasado por valor (en lugar de por referen-
cia). Si hacemos un seguimiento más exhaustivo del
programa, vemos que cuando llamamos a la función
cambiavalor en la línea 8, el programa salta a la
línea 1 para ejecutar la función. Allí, se crea una
nueva variable llamada vpi, y se copia el valor de pi
en ella. Esto se representa en el esquema de la
Figura 4.

pi

vpi

...
145 146 147 148 149 150 15
  • Links de descarga
http://lwp-l.com/pdf1254

Comentarios de: Punteros en ANSI C (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad