Você está na página 1de 64

I.P.E.T.

Juan XXIII

Laboratorio de Computadoras

Gustavo A. Yarce

Paraná - Entre Ríos


2010
2 Gustavo A. Yarce
Índice general

1. Introducción 7
1.1. Problemas computacionales . . . . . . . . . . . . . . . . . . . . . . 7
1.2. Etapas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1. Definición del problema . . . . . . . . . . . . . . . . . . . . 7
1.2.2. Análisis del problema . . . . . . . . . . . . . . . . . . . . . . 7
1.2.3. Programación . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.4. Prueba . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.5. Algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3. PROGRAMACIÓN MODULAR . . . . . . . . . . . . . . . . . . . 9
1.4. Documentación de Programas . . . . . . . . . . . . . . . . . . . . . 10

2. El Lenguaje C 11
2.1. Marco histórico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Características . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3. Creación del programa . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4. Compilación de C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.1. Descripción . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5. Entorno de programación . . . . . . . . . . . . . . . . . . . . . . . . 13
2.6. Bibliotecas estándares . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.7. Componentes del lenguaje C . . . . . . . . . . . . . . . . . . . . . . 15
2.8. Estructura de un fichero fuente . . . . . . . . . . . . . . . . . . . . 16
2.9. Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.10. CONSTANTES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.11. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.11.1. Variables locales y globales . . . . . . . . . . . . . . . . . . . 18
2.12. Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.12.1. Calificadores de tipo . . . . . . . . . . . . . . . . . . . . . . 20
2.13. Secuencias de escape . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.14. Inclusión de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.15. Operadores aritméticos . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.16. Operadores de asignación . . . . . . . . . . . . . . . . . . . . . . . . 23

3
4 Gustavo A. Yarce

2.17. Jerarquía de los operadores . . . . . . . . . . . . . . . . . . . . . . . 24


2.18. Sentencia printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.19. Sentencia scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.20. Pantalla en modo texto . . . . . . . . . . . . . . . . . . . . . . . . . 29

3. Control de flujo de ejecución 33


3.1. Operadores relacionales . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2. Estructura IF...ELSE . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2.1. Estructura IF...ELSE IF... . . . . . . . . . . . . . . . . . . . 34
3.3. Estructura SWITCH . . . . . . . . . . . . . . . . . . . . . . . . . . 35

4. Control de Programas 37
4.1. Instrucción FOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2. Instrucción WHILE . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.3. Instrucción DO...WHILE . . . . . . . . . . . . . . . . . . . . . . . . 39

5. Funciones 41
5.1. Paso de parámetros a una función . . . . . . . . . . . . . . . . . . . 47

6. Arrays 51
6.1. Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.2. Operaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.3. Múltiples dimensiones . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.4. Paso de parámetros a una función . . . . . . . . . . . . . . . . . . . 53

7. Gráficos 55
7.1. Librería WinbGim . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.2. Instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.2.1. initwindow . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.2.2. getmaxx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.2.3. getmaxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.2.4. moveto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2.5. setcolor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2.6. setbkcolor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.2.7. cleardevice . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.3. funciones de dibujo . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.3.1. putpixel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.3.2. line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.3.3. lineto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.3.4. circle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.3.5. rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Laboratorio de Computadoras 5

7.4. Funciones de escritura de texto . . . . . . . . . . . . . . . . . . . . 58


7.4.1. outtextxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.4.2. settextstyle . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

8. Cadenas de texto 59
8.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.2. Comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

9. Punteros 61
9.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.2. Punteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9.2.1. Declaración . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9.2.2. Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9.3. Asignación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
9.4. Aritmética de direcciones . . . . . . . . . . . . . . . . . . . . . . . . 64
Prologo
Este documento no pretende ser un libro completo sobre programación, es una
ayuda para el alumno, para su utilización como guía de aprendizaje.
Se tiene como objetivo presentar los conceptos básicos y las características gen-
erales del lenguaje C que posibiliten la realización de programas para la repre-
sentación de soluciones de problemas reales en una computadora.
Los temas tratados y el desarrollo que se realiza sobre ellos persiguen la enseñan-
za en entornos educativos técnicos de nivel medio que necesitan conocimientos de
informática como una herramienta para la resolución de problemas.
Se prioriza la enseñanza de una metodología de programación correcta tratando
de conservar la facilidad de uso como herramienta. Siempre se considera que lo
más importante es adquirir una base de conocimientos que permita una posterior
evolución hacia conocimientos relacionados con la Electrónica y la programación.
Capítulo 1

Introducción

1.1. Problemas computacionales


Así como cada persona tiene formas de encarar un problema y su propia man-
era de solucionarlo, computacionalmente hablando podemos hacer una analogía.
Ante la presentación de un problema encarar la mejor forma de resolverlo para
arribar al resultado esperado y correcto es un desafío. Para ello debemos compren-
der exactamente qué se pide, qué resultados se pretenden y que restricciones y/o
condiciones existen. Para realizar lo antes dicho dividiremos la resolución de un
problema en etapas.

1.2. Etapas
1.2.1. Definición del problema
Está dada por la formulación del problema en forma correcta y completa. Esta
enunciación de lo que se desea es primordial para el éxito de la resolución.

1.2.2. Análisis del problema


A partir del estudio del problema se deberá identificar y conocer las partes
princi-pales del mismo y de esa manera determinar los siguientes conjuntos:

Datos: es la información con que contamos para resolver el problema

Resultados: es lo que se desea obtener.

Condiciones: una o más relaciones que vinculan los dos conjuntos anteriores
y que permitirán plantear la solución del problema.

7
8 Gustavo A. Yarce

1.2.3. Programación
Esta etapa consiste en obtener la solución del problema dado. Se divide en dos
subetapas:

Elección y creación del método: Se trata de buscar un procedimiento o


método general que permita resolver el problema planteado utilizando una
computadora.

Codifiación : Consiste en expresar el método elegido en un lenguaje, llama-


do lenguaje de programación, que pueda se interpretado por la computadora.

Programa
Un programa es una sucesión de instrucciones que pueden ser ejecutadas por
la PC. De modo general la PC comprende, sin traducción previa, los llamados
comando en lenguaje máquina, que son específicos del procesador.
Este tipo de lenguaje resulta ser bastante engorroso para realizar operaciones sim-
ples. Con el fin de vencer esta dificultad, se desarrollaron los lenguajes superiores de
programación. El programador no tiene que preocuparse por la estructura interna
de la PC, ya que puede trabajar en un lenguaje relativamente simple, transformar
un determinado algoritmo en un programa adecuado.
Un lenguaje de programación lo único que realiza es la traducción escrita en lengua-
je máquina de las diferentes instrucciones escrita en un lenguaje superior.
Aquí pueden acreditarse dos procedimientos:

1. El programa usuario puede traducirse totalmente, antes de la ejecución. El


programa que realiza la traducción se llama compilador.

2. Los diferentes comandos son traducidos e, inmediatamente después ejecuta-


dos, aún antes de que el programa traductor prosiga con la siguiente ejecu-
ción. El programa de traducción que trabaja de acuerdo con este proced-
imiento, es un INTERPRETE.

1.2.4. Prueba
Esta etapa consiste en la ejecución del código del método elegido, es decir,
suministrar los datos al computador, y obtener los resultados. Luego se analizarán
los mismos determinando si son realmente los esperados. Caso contrario, deberán
analizarse las etapas previas, comenzando por la última hacia atrás, y realizar
las modificaciones necesarias, repitiendo esta proceso hasta obtener los resultados
esperados.
Laboratorio de Computadoras 9

1.2.5. Algoritmo
En relación al algoritmo, deseamos aún entrar con detalle en unos conceptos
que son independientes del procedimiento de notación y de la descripción formal.
En primer lugar tenemos:

FINITEZ: el algoritmo completo se tiene que representar en una sucesión


finita de caracteres.

EFECTIVIDAD: todos los pasos u operaciones que forman el algoritmo,


han de ser ejecutables. Aquí hay que pensar en las limitaciones técnicas de
la PC.

TERMINACIÓN: por razones de carácter practico, con frecuencia esta


uno interesado que, en muchos procesos, conduzca a un final.

DETERMINISMO: un algoritmo determinativo es una serie de pasos de


procesamiento, cuyo desarrollo está claramente prescrito.

EFICIENCIA: para un determinado problema, existen, generalmente, var-


ios algoritmos diferentes. Se distinguen por el volumen de trabajo que hay
que desarrollar para alcanzar lo mismo.

1.3. PROGRAMACIÓN MODULAR


Es un método de diseño y tiende a dividir el problema en partes perfecta-
mente diferenciadas que puedan ser analizadas, resueltas y puestas a punto por
separa-do. Para atacar el análisis de un problema, y siguiendo el diseño Top-Down,
se pue-den utilizar criterios de programación modular para dividirlos en partes
indepen-dientes, probando cada uno por separado y realizando su recomposición
ascen-dente. Cada una de las partes independientes se llama Módulo y para su
determinación se deben tener en cuenta los siguientes criterios:

un módulo debe corresponder a una función lógica perfectamente bien defini-


da.

los módulos deben ser pequeños para que sean claros y de poca complejidad.

un módulo debe tener una estructura de caja negra, es decir la salida debe
ser exclusivamente función de la entrada.

cada módulo deber tener una única entrada y una única salida.
10 Gustavo A. Yarce

1.4. Documentación de Programas


La documentación es un aspecto muy importante en la programación. Sin em-
bargo, generalmente los programadores principiantes suelen dejar de lado el pro-
ceso de documentación por falta de dedicación o simple desconocimiento de su
relevancia. La documentación es todo el material anexo a un programa que no
constituye parte del código que se compila. Todo esto sirve para que el manten-
imiento, la reparación y la actualización del programa sean rápidas y seguras. En el
caso de que estas tareas deban desarrollarlas otro programador la documentación
será imprescindible. Pero más aún, cuando hayan pasado varios meses de hecho
el programa, para usted mismo será imprescindible la documentación porque ya
no podrá recordar claramente lo que hizo y le constará mucho volver a entender
el programa para poder hacer las modificaciones necesarias. La documentación
puede realizarse en el mismo archivo de texto del programa mediante comentarios.
Los comentarios poseen una sintaxis particular y son totalmente ignorados por el
compilador. Esta documentación es denominada Interna ya que se encuentra en
el mismo archivo de texto del programa. Por otra parte, cualquier tipo de infor-
mación que no se encuentre en el mismo programa se denomina documentación
externa. La documentación externa puede consistir por ejemplo en gráficas, texto
explicativo, manual de usuario, algoritmos en pseudocódigo, etc.
Para convertir el algoritmo en un programa, se ha mostrado como muy adecua-
da la utilización de los llamados diagramas de flujo.Un diagrama de flujo es una
representación gráfica del programa, con la ayuda de símbolos.
Capítulo 2

El Lenguaje C

2.1. Marco histórico


El lenguaje C fue creado entre 1970 y 1972 por Brian KERNIGHAN y Dennis
RITCHIE para escribir el código del sistema operativo UNIX. Desde su nacimiento
se fue implantando como el lenguaje de programación de sistemas favorito para
muchos programadores, sobre todo por ser un lenguaje que conjugaba la abstrac-
ción de los lenguajes de alto nivel con la eficiencia del lenguaje máquina. Los
programadores de sistemas que trabajaban sobre MS-DOS y Macintosh también
utilizaban C, con lo cual la práctica totalidad de aplicaciones de sistema para mi-
croordenadores y para sistemas UNIX está escrito en este lenguaje. En 1983 el
lenguaje C se convierte en un estándar internacional ANSI C (que es el que desar-
rollaremos). Este estándar incluye tanto la definición del lenguaje como una enorme
biblioteca de funciones para entrada/salida, tratamiento de textos, matemáticas,
etc.
A mediados de los ochenta se crea el C++, extensión de C orientada a objetos. El
C++ se convierte en estándar ISO en 1998. En el momento actual, el lenguaje C
no va a modificarse más. Será el C++ el que incorporará nuevos cambios.

2.2. Características
El lenguaje C tiene muy pocas reglas sintácticas, sencillas de aprender. Su léx-
ico es muy reducido: tan solo 32 palabras. A menudo se le llama lenguaje de medio
nivel, más próximo al código máquina que muchos lenguajes de más alto nivel. Y
por eso mismo es un lenguaje muy eficiente. Permite el uso del lenguaje ensam-
blador en partes del código, trabaja a nivel de bit, y permite modificar los datos
con operadores que manipulan bit a bit la información. También se puede acceder
a las diferentes posiciones de memoria conociendo su dirección. El lenguaje C per-

11
12 Gustavo A. Yarce

mite con facilidad la programación modular, creando unidades independientes que


pueden compilarse de forma independiente, que pueden posteriormente enlazarse.
Así, se crean funciones o procedimientos, que se pueden compilar y almacenar,
creando así bibliotecas de código ya editado y compilado que resuelve distintas
operaciones. Cada programador puede diseñar sus propias bibliotecas, que sim-
plifican luego considerablemente el trabajo futuro. El ANSI C posee una amplia
colección de bibliotecas de funciones estándar y normalizadas.

2.3. Creación del programa


Se puede crear un archivo que contenga el programa completo. Se puede usar
cualquier editor de textos ordinario con el que se este familiarizado. En caso de
usar un entorno Por convención el nombre del archivo debe terminar con “.c” por
ejemplo: miprograma.c. El contenido del archivo deberá obedecer la sintaxis de C.

2.4. Compilación de C
En el siguiente apartado se muestran las distintas etapas que cubre el compi-
lador para obtener el código ejecutable:

1. Código Fuente

2. Preprocesador

3. Compilador

4. Código Ensamblador

5. Ensamblador

6. Librerías

7. Código Objeto

8. Ligador

9. Código Ejecutable
Laboratorio de Computadoras 13

2.4.1. Descripción
El proceso puede ser el globalmente dividido en varios programas:
- Preprocesador: el proceso de archivo de origen antes de la compilación. Que,
por ejemplo, controlar y sustituir los archivos de macros e incluir en su fuente. -
Compilador: transformar su archivo de origen en el código de ensamble (procesador
de lenguaje humanamente legible) - Ensamblador: toma el código de ensamble
y generar código legible por máquina (código objeto binario) - Linker: reúne y
resuelve objeto códigos juntos para crear un único ejecutable.

2.5. Entorno de programación


Un entorno de programación incluye todas las distintas herramientas de pro-
gramación necesarias para trabajar con un lenguaje de programación en particular.
El entorno de C incluye los siguientes componentes:

Editores de texto: Permite introducir y modificar el código fuente C.

Administrador de proyectos: Un Proyecto es un centro para la gestión los


archivos de origen y diferentes opciones. Le ayuda a navegar a través de
su código y configurar fácilmente los distintos parámetros, como el tipo de
programa que está haciendo (GUI, consola, DLL...).

El preprocesador: Transforma el programa fuente, convirtiéndolo en otro


archivo fuente predigerido. Las transformaciones incluyen:

• Eliminar los comentarios.


• Incluir en el fuente el contenido de los ficheros declarados con #include
<fichero>(a estos ficheros se les suele llamar cabeceras)
• Sustituir en el fuente las macros declaradas con #define (ej. #define
CIEN 100)

El compilador: Convierte el código fuente entregado por el preprocesador en


un archivo en lenguaje máquina: fichero objeto, en un código que comprende
el ordenador (código máquina). Algunos compiladores pasan por una fase
intermedia en lenguaje ensamblador.

El enlazador o linkeador: Un fichero objeto es código máquina, pero no se


puede ejecutar, porque le falta código que se encuentra en otros archivos
binarios. El enlazador genera el ejecutable binario, a partir del contenido de
los ficheros objetos y de las bibliotecas.
14 Gustavo A. Yarce

Depurador o debugger: Habitualmente los programas no se ejecutan correc-


tamente la primera vez después de compilarlos. Mientras unos errors son
fáciles de encontrar y corregir, otros pueden ser más difíciles de encontrar
debido a la complejidad de los programas o inexperiencia del programador.
El depurador o debugger es una herramienta compleja que nos puede ayudar
a rastrear el código y corregir esos errores.

Las bibliotecas contienen el código de funciones precompiladas, a las que el archivo


fuente llama (por ejemplo printf).

El programa editado en C se llama fichero fuente. El archivo donde se almacena


ese código tendrá un nombre (el que se quiera) y la extensión .cpp, o .c. Un
programa no es más que archivo de texto. Al compilar, del fichero fuente se llega
al código máquina, con el mismo nombre que el archivo donde está el código fuente,
y con la extensión .obj. Casi con toda probabilidad en código fuente hará uso de
funciones que están ya definidas y precompiladas en las bibliotecas. Ese código
precompilado está en archivos con la extensión .lib. Desde luego, para hacer uso
de una función predefinida, es necesario conocer su existencia y tener localizada
la biblioteca donde está precompilada; eso es parte del aprendizaje de un lenguaje
de programación, aunque también se disponen de grandes índices de funciones, de
fácil acceso para su consulta. Con el archivo .obj y los necesarios .lib que se deseen
emplear, se procede al linkado que genera un fichero ejecutable con la extensión
.exe.

Ejemplo de programa en C

#include <stdio.h>
main()
{
/* Escribe un mensaje */
printf (‘‘Hola, mundo\n’’);
}

2.6. Bibliotecas estándares


El lenguaje C es muy simple. Carece de tipos y servicios que forman parte
de otros lenguajes. No tiene tipo booleano, ni manejo de cadenas, ni manejo de
memoria dinámica.
Laboratorio de Computadoras 15

No obstante, el estándar de C define un conjunto de bibliotecas de funciones,


que necesariamente vienen con todo entorno de compilación de C y que satisfacen
estos servicios elementales.
Las interfaces de estos servicios vienen definidas en unos ficheros cabeceras
(header files). El nombre de estos ficheros suele terminar en .h

Algunos de los servicios proporcionados por las bibliotecas estándares son:

entrada y salida de datos (stdio.h)

manejo de cadenas (string.h)

memoria dinámica (stdlib.h)

rutinas matemáticas (math.h)

2.7. Componentes del lenguaje C


Estructuras de datos

literales

tipos básicos (todos numéricos)

tipos enumerados

tipos estructurados (struct, union)

punteros y vectores

Construcciones algorítmicas

construcciones condicionales (if,switch)

construcciones iterativas(while,for,do...while)

subrutinas (funciones)

Además de lo anterior, el C tiene otros elementos:

comentarios
16 Gustavo A. Yarce

inclusión de ficheros

macros

compilación condicional

2.8. Estructura de un fichero fuente


Un fichero fuente en lenguaje C tendrá esta estructura típica:

#include <biblioteca1.h>
#include <biblioteca2.h>
... declaraciones de funciones ...

... definiciones (cuerpos de funciones) ...


... declaraciones de variables globales ...

main()
{
... cuerpo del main ...
}

... otras definiciones de funciones ...

main es simplemente una función más del programa, con la particularidad de


que es el punto de entrada al programa.

2.9. Comentarios
En C, tienen la forma /* cualquier texto */

2.10. CONSTANTES
Se define a una constante, como un elemento cuyo valor que no puede alterarse
en el transcurso de la ejecución de un algoritmo. Por ejemplo: 123, ’López’, 3.14459.

Las constantes mantienen su valor a lo largo de todo el programa.


Laboratorio de Computadoras 17

Para indicar al compilador que se trata de una constante, usaremos la directiva


#define:

# define <identificador> <valor>

Observa que no se indica el punto y coma de final de sentencia ni tampoco el


tipo de dato.
La directiva #define no sólo nos permite sustituir un nombre por un valor numéri-
co, sinó también por una cadena de caracteres. El valor de una constante no puede
ser modificado de ninguna manera.

Ejemplo 2.1 Constantes


/* Uso de las constantes */
#include <stdio.h>
#define pi 3.1416
#define escribe printf
main() /* Calcula el perímetro */
{
int r;
escribe("Introduce el radio: ");
scanf("%d",&r);
escribe("El perímetro es: %f",2*pi*r);
}

2.11. Variables
En un programa existen otros elementos cuyo valor cambia durante la ejecución
del mismo, llamados variables.
Una variable es un elemento o lugar asociado a un valor el que puede variar con-
forme se ejecuta el algoritmo, se representa por un nombre que identifica a una
posición de memoria donde puede asignarse o almacenarse un único valor por vez.
Para proponer el nombre de una variable observaremos tres reglas simples:

1. Utilizar sólo letras y/o dígitos, comenzando siempre con una letra.

2. No utilizar las palabras claves o reservadas del lenguaje de codificación (por


ahora, no endremos incovenientes en este aspecto, pues usaremos diagramas
18 Gustavo A. Yarce

de flujo); o para las funciones internas o predefinidas: RC, SEN, TRUNC,


LN, etc.

3. No hacer distinción entre mayúsculas y minúsculas. Esto implica que VEN-


TA, venta y Venta, constituyen en el algoritmo la misma variable.

Una variable sólo puede pertenecer a un tipo de dato. Para poder utilizar una
variable, primero tiene que ser declarada:

[calificador] <tipo> <nombre>

Es posible inicializar y declarar más de una variable del mismo tipo en la misma
sentencia:

[calificador] <tipo> <nombre1>,<nombre2>=<valor>,<nombre3>=<valor>

Ejemplo 2.2 Variables


/* Uso de las variables */

#include <stdio.h>
#include <conio2.h>

main() /* Suma dos valores */


{
int num1=4,num2,num3=6;
printf("El valor de num1 es %d",num1);
printf("\nEl valor de num3 es %d",num3);
num2=num1+num3;
printf("\nnum1 + num3 = %d",num2);
getch();
}

2.11.1. Variables locales y globales


Las variables pueden ser de dos tipos según el lugar en que las declaremos:
globales o locales.

La variable global se declara antes de la main( ). Puede ser utilizada en


cualquier parte del programa y se destruye al finalizar éste.
Laboratorio de Computadoras 19

La variable local se declara después de la main( ), en la función en que vaya


a ser utilizada. Sólo existe dentro de la función en que se declara y se destruye al
finalizar dicha función.

Ejemplo 2.3 Variables locales y globales

/* Declaración de variables */

#include <stdio.h>
#include <conio2.h>

int a;
main() /* Muestra dos valores */
{
int b=4;
printf("b es local y vale %d",b);
a=5;
printf("\na es global y vale %d",a);
getch)();
}

2.12. Tipos de datos


En C existen básicamente cuatro tipos de datos, aunque como se verá después,
podremos definir nuestros propios tipos de datos a partir de estos cuatro. A con-
tinuación se detalla su nombre, el tamaño que ocupa en memoria y el rango de sus
posibles valores.

Tipo Tamaño Rango de Valores


char 1 byte -128 a 127
int 2 bytes -32768 a 32767
float 4 bytes 3.4 E-38 a 3.4 E+38
double 8 bytes 1.7 E-308 a 1.7 E+308

Cuadro 2.1: Tipos de datos


20 Gustavo A. Yarce

2.12.1. Calificadores de tipo


Los calificadores de tipo tienen la misión de modificar el rango de valores de
un determinado tipo de variable. Estos calificadores son cuatro:

signed: Le indica a la variable que va a llevar signo. Es el utilizado por defecto.


Tipo Tamaño Rango de Valores
signed char 1 byte -128 a 127
signed int 2 bytes -32768 a 32767

Cuadro 2.2: Tipo signed

unsigned: Le indica a la variable que no va a llevar signo (valor absoluto).

Tipo Tamaño Rango de Valores


unsigned char 1 byte 0 a 255
unsigned int 2 bytes 0 a 65535

Cuadro 2.3: Tipo unsigned

short: Rango de valores en formato corto (limitado). Es el utilizado por defecto.

Tipo Tamaño Rango de Valores


short char 1 byte -128 a 127
short int 2 bytes -32768 a 32767

Cuadro 2.4: Tipo short

long: Rango de valores en formato largo (ampliado).

Tipo Tamaño Rango de Valores


long int 4 bytes -2.147.483.648 a 2.147.483.647
long double 10 bytes -3.36 E-4932 a 1.18 E+4932

Cuadro 2.5: Tipo long

10mm
Laboratorio de Computadoras 21

2.13. Secuencias de escape


Ciertos caracteres no representados gráficamente se pueden representar medi-
ante lo que se conoce como secuencia de escape.
A continuación vemos una tabla de las más significativas:
\n salto de línea
\b retroceso
\t tabulación horizontal
\v tabulación vertical
\\ contrabarra
\f salto de página
\’apóstrofe
\" comillas dobles
\0 fin de una cadena de caracteres

/* Uso de las secuencias de escape */

#include <stdio.h>
#include <conio2.h>

main() /* Escribe diversas sec. de escape */


{
printf("Me llamo \"Nemo\" el grande");
printf("\nDirección: C\\ Mayor 25");
printf("\nHa salido la letra \’L\’");
printf("\nRetroceso\b");
printf("\n\tEsto ha sido todo");
getch();
}

2.14. Inclusión de ficheros


En la programación en C es posible utilizar funciones que no esten incluídas
en el propio programa. Para ello utilizamos la directiva #include, que nos permite
añadir librerías o funciones que se encuentran en otros ficheros a nuestro programa.

Para indicar al compilador que vamos a incluir ficheros externos podemos hac-
erlo de dos maneras (siempre antes de las declaraciones).
22 Gustavo A. Yarce

1. Indicándole al compilador la ruta donde se encuentra el fichero.

#include "misfunc.h"
#include "c:\includes\misfunc.h"

2. Indicando que se encuentran en el directorio por defecto del compilador.

#include <misfunc.h>

2.15. Operadores aritméticos


Existen dos tipos de operadores aritméticos:

1. binarios:

+ Suma
-Resta
* Multiplicación
/ División
% Módulo (resto)

Su sintaxis es:

<variable1><operador><variable2>

2. unarios:

++ Incremento (suma 1)
- -Decremento (resta 1)
- Cambio de signo

Su sintaxis es:

<variable><operador> y al revés, <operador><variable>.


Laboratorio de Computadoras 23

Ejemplo 2.4 Operadores

/* Uso de los operadores aritméticos */

#include <stdio.h>
#include <conio2.h>

main() /* Realiza varias operaciones */


{
int a=1,b=2,c=3,r;
r=a+b;
printf("%d + %d = %d\n",a,b,r);
r=c-a;
printf("%d - %d = %d\n",c,a,r);
b++;
printf("b + 1 = %d",b);
getch();
}

2.16. Operadores de asignación


La mayoría de los operadores aritméticos binarios explicados en el capítulo
anterior tienen su correspondiente operador de asignación:

= Asignación simple
+= Suma
-= Resta
*= Multiplicación
/= División
%= Módulo (resto)

Con estos operadores se pueden escribir, de forma más breve, expresiones del
tipo:

n=n+3 se puede escribir n+=3

k=k*(x-2) lo podemos sustituir por k*=x-2


24 Gustavo A. Yarce

Ejemplo 2.5

/* Uso de los operadores de asignación */

#include <stdio.h>
#include <conio2.h>

main() /* Realiza varias operaciones */


{
int a=1,b=2,c=3,r;
a+=5;
printf("a + 5 = %d\n",a);
c-=1;
printf("c - 1 = %d\n",c);
b*=3;
printf("b * 3 = %d",b);
getch();
}

2.17. Jerarquía de los operadores


Será importante tener en cuenta la precedencia de los operadores a la hora de
trabajar con ellos:

( ) Mayor precedencia
++, - -
*, /, %
+, -Menor precendencia

Las operaciones con mayor precedencia se realizan antes que las de menor
precedencia.
Si en una operación encontramos signos del mismo nivel de precedencia, dicha op-
eración se realiza de izquierda a derecha. A continuación se muestra un ejemplo
sobre ello:

a*b+c/d-e

1. a*b resultado = x

2. c/d resultado = y
Laboratorio de Computadoras 25

3. x+y resultado = z

4. z-e

Fijarse que la multiplicación se resuelve antes que la división ya que está situada
más a la izquierda en la operación. Lo mismo ocurre con la suma y la resta.

Ejemplo 2.6
/* Jerarquía de los operadores */

#include <stdio.h>
#include <conio2.h>

main() /* Realiza una operación */


{
int a=6,b=5,c=4,d=2,e=1,x,y,z,r;
x=a*b;
printf("%d * %d = %d\n",a,b,x);
y=c/d;
printf("%d / %d = %d\n",c,d,y);
z=x+y;
printf("%d + %d = %d\n",x,y,z);
r=z-e;
printf("%d = %d",r,a*b+c/d-e);
getch();
}

2.18. Sentencia printf


La rutina printf permite la aparición de valores numéricos, caracteres y cadenas
de texto por pantalla.
El prototipo de la sentencia printf es el siguiente:

printf(control,arg1,arg2...);

En la cadena de control indicamos la forma en que se mostrarán los argumentos


posteriores. También podemos introducir una cadena de texto ( sin necesidad de
argumentos ), o combinar ambas posibilidades, así como Secuencias de escape
(2.13).
En el caso de que utilicemos argumentos deberemos indicar en la cadena de control
26 Gustavo A. Yarce

tantos modificadores como argumentos vayamos a presentar.


El modificador está compuesto por el caracter

Ejemplo 2.7
/* Uso de la sentencia printf() 1. */

#include <stdio.h>
#include <conio2.h>

main() /* Saca por pantalla una suma */


{
int a=20,b=10;
printf("El valor de a es %d\n",a);
printf("El valor de b es %d\n",b);
printf("Por tanto %d+%d=%d",a,b,a+b);
getch();
}

Los modificadores más utilizados son:

%c Un único caracter
%d Un entero con signo, en base decimal
%u Un entero sin signo, en base decimal
%o Un entero en base octal
%x Un entero en base hexadecimal
%e Un número real en coma flotante, con exponente
%f Un número real en coma flotante, sin exponente
%s Una cadena de caracteres
%p Un puntero o dirección de memoria

Ejemplo 2.8

/* Uso de la sentencia printf() 2. */

#include <stdio.h>
#include <conio2.h>

main() /* Modificadores 1 */
{
Laboratorio de Computadoras 27

char cad[]="El valor de";


int a=-15;
unsigned int b=3;
float c=932.5;
printf("%s a es %d\n",cad,a);
printf("%s b es %u\n",cad,b);
printf("%s c es %e o %f",cad,c,c);
getch();
}

El formato completo de los modificadores es el siguiente:

% [signo] [longitud] [.precisión] [l/L] conversión

Signo: indicamos si el valor se ajustará a la izquierda, en cuyo caso utilizare-


mos el signo menos, o a la derecha ( por defecto ).

Longitud: especifica la longitud máxima del valor que aparece por pantalla.
Si la longitud es menor que el número de dígitos del valor, éste aparecerá
ajustado a la izquierda.

Precisión: indicamos el número máximo de decimales que tendrá el valor.

l/L: utilizamos l cuando se trata de una variable de tipo long y L cuando es


de tipo double.

Ejemplo 2.9
/* Uso de la sentencia printf() 3. */

#include <stdio.h>
#include <conio2.h>

main() /* Modificadores 2 */
{
char cad[ ]="El valor de";
int a=25986;
long int b=1976524;
float c=9.57645;
printf("%s a es %9d\n",cad,a);
28 Gustavo A. Yarce

printf("%s b es %ld\n",cad,b);
printf("%s c es %.3f",cad,c);
getch();
}

2.19. Sentencia scanf


La rutina scanf permite entrar datos en la memoria del ordenador a través del
teclado.
El prototipo de la sentencia scanf es el siguiente:

scanf(control,arg1,arg2...);

En la cadena de control indicaremos, por regla general, los modificadores 2.18


que harán referencia al tipo de dato de los argumentos. Al igual que en la senten-
cia printf los modificadores 2.18 estarán formados por el caracter % seguido de un
caracter de conversión. Los argumentos indicados serán, nuevamente, las variables.

La principal característica de la sentencia scanf es que necesita saber la posición


de la memoria del ordenador en que se encuentra la variable para poder almace-
nar la información obtenida. Para indicarle esta posición utilizaremos el símbolo
ampersand ( & ), conocido como operador de dirección, que colocaremos delante
del nombre de cada variable. ( Esto no será necesario en los arrays ).

Ejemplo 2.10
/* Uso de la sentencia scanf(). */

#include <stdio.h>
#include <conio2.h>

main() /* Solicita dos datos */


{
char nombre[10];
int edad;
printf("Introduce tu nombre: ");
scanf("%s",nombre);
printf("Introduce tu edad: ");
Laboratorio de Computadoras 29

scanf("%d",&edad);
getch();
}

2.20. Pantalla en modo texto


Las funciones añadidas para manejo de la pantalla en Lenguaje C, se encuen-
tran accesibles a través del fichero de cabecera c̈onio2.h.̈

En él encontramos funciones como:

gotoxy - Desplaza el cursor a ciertas coordenadas.

textcolor - Cambia el color del texto (el de primer plano).

textbackground - Cambia el color del texto (el de fondo).

textattr - Cambia el color (fondo y primer plano) del texto.

cprintf - Escribe un mensaje en color.

cputs - Escribe una cadena de texto en color.

clrscr - Borra la pantalla.

clreol - Borra hasta el final de la línea actual.

textmode - Cambia el modo de pantalla.

getche - Espera hasta que se pulse una tecla, y la muestra en pantalla.

getch - Espera hasta que se pulse una tecla, pero no la muestra en pantalla.

kbhit - Comprueba si se ha pulsado alguna tecla (pero no espera).

wherex - Devuelve la coordenada ẍ¨(columna) en que se encuentra el cursor.

wherey - Devuelve la coordenada ÿ¨(fila) en que se encuentra el cursor.

window - Permite crear una ventana dentro de la pantalla. A partir de


entonces, las órdenes como g̈otoxys̈e referirán sólo a esa ventana, no al total
de la pantalla.
30 Gustavo A. Yarce

Los colores de la pantalla se indican por números. Por ejemplo: 0 es el negro,


1 es el azul oscuro, 2 el verde, 3 el azul claro, 4 el rojo, etc. Aun así, para no tener
que recordarlos, tenemos definidas constantes con su nombre en inglés:

BLACK

BLUE

GREEN

CYAN

RED

MAGENTA

BROWN

LIGHTGRAY

DARKGRAY

LIGHTBLUE

LIGHTGREEN

LIGHTCYAN

LIGHTRED

LIGHTMAGENTA

YELLOW

WHITE

Una última consideración: en MsDos sólo se pueden usar como colores de fondo
los 7 primeros: desde BLACK hasta LIGHTGRAY. Esto se puede evitar con las
pantallas VGA, a cambio de perder la posibilidad de que el texto parpadee, pero
no voy a entrar en esos detalles. El caso es que n̈ormalmentes̈i hacemos algo como

textbackground(LIGHTBLUE);

no obtendremos los resultados esperados, sino que será como si hubiésemos


utilizado el equivalente en el rango de 0 a 7:
Laboratorio de Computadoras 31

textbackground(BLUE);

Ejemplo 2.11 #include <conio2.h> /* Para funciones de pantalla */

int i,j; /* Para los bucles "for" */

main()
{
textbackground(BLUE); /* Fondo de la pantalla en azul */
clrscr(); /* Borro la pantalla */
for(i=0; i<=1; i++) /* Dos columnas */
for(j=0; j<=15; j++) /* Los 16 colores */
{
gotoxy(10+ 40*i , 3+j); /* Coloco el cursor */
textcolor(j); /* Elijo el color */
if (j == 0) /* Si el color es 0 (negro) */
textbackground(LIGHTGRAY); /* dejo fondo gris */
else /* Si es otro color */
textbackground(BLACK); /* dejo fondo negro */
cprintf(" Este es el color %d ",j); /* Escribo en color */
}
getch(); /* Final: espero a que se pulse una tecla, sin mostrarla */
}
32 Gustavo A. Yarce
Capítulo 3

Control de flujo de ejecución

Este tipo de sentencias permiten variar el flujo del programa en base a unas
determinadas condiciones. Existen varias estructuras diferentes:

3.1. Operadores relacionales


Los operadores relacionales se utilizan para comparar el contenido de dos vari-
ables.

En C existen seis operadores relacionales básicos:

>Mayor que
<Menor que
>= Mayor o igual que
<= Menor o igual que
== Igual que
!= Distinto que

El resultado que devuelven estos operadores es 1 para Verdadero y 0 para Falso.

Si hay más de un operador se evalúan de izquierda a derecha. Además los


operadores == y != están por debajo del resto en cuanto al orden de precedencia.

3.2. Estructura IF...ELSE


Sintaxis:

33
34 Gustavo A. Yarce

if (condición)
sentencia1;
else
sentencia2;

La parte del else es optativa. La condicón se evalúa, si es verdadera, la senten-


cia1 se ejecuta. Si la condición es falsa y si existe un else, la sentencia2 se ejecuta.

Ejemplo 3.1 /* Uso de la sentencia condicional IF. */

#include <stdio.h>

main() /* Simula una clave de acceso */


{
int usuario,clave=18276;
printf("Introduce tu clave: ");
scanf("%d",&usuario);
if(usuario==clave)
printf("Acceso permitido");
else
printf("Acceso denegado");
}

3.2.1. Estructura IF...ELSE IF...


Sintaxis:

if (condición) sentencia1;
else if (condición) sentencia2;
else if (condición) sentencia3;
else sentencia4;

Esta secuencia de instrucciones if es la forma mas general de escribir una de-


cisión múltiple.
Las condiciones se evaluan en orden; si cualquier condición es verdadera, la senten-
cia asociada a ella se ejecuta, y esto termina toda la cadena. La sentencia puede
ser una única sentencia o un grupo de sentencias contenidas entre un par de llaves.
Laboratorio de Computadoras 35

Ejemplo 3.2
/* Uso de la sentencia condicional ELSE...IF. */

#include <stdio.h>

main() /* Escribe bebé, niño o adulto */


{
int edad;
printf("Introduce tu edad: ");
scanf("%d",&edad);
if (edad<1)
printf("Lo siento, te has equivocado.");
else if (edad<3) printf("Eres un bebé");
else if (edad<13) printf("Eres un niño");
else printf("Eres adulto");
}

switch (variable){
case contenido_variable1: sentencias;
case contenido_variable1: sentencias;
default:

3.3. Estructura SWITCH


Esta estructura se suele utilizar en los menús, de manera que según la opción
seleccionada se ejecuten una serie de sentencias.
Su sintaxis es:

switch (variable){
case contenido_variable1:
sentencias;
break;
case contenido_variable2:
sentencias;
break;
default:
sentencias;
}
36 Gustavo A. Yarce

Cada case puede incluir una o más sentencias sin necesidad de ir entre llaves,
ya que se ejecutan todas hasta que se encuentra la sentencia BREAK. La variable
evaluada sólo puede ser de tipo entero o caracter. default ejecutará las sentencias
que incluya, en caso de que la opción escogida no exista.

Ejemplo 3.3
/* Uso de la sentencia condicional SWITCH. */

#include <stdio.h>

main() /* Escribe el día de la semana */


{
int dia;
printf("Introduce el día: ");
scanf("%d",&dia);
switch(dia){
case 1: printf("Lunes"); break;
case 2: printf("Martes"); break;
case 3: printf("Miércoles"); break;
case 4: printf("Jueves"); break;
case 5: printf("Viernes"); break;
case 6: printf("Sábado"); break;
case 7: printf("Domingo"); break;
}
}
Capítulo 4

Control de Programas

La mayor parte de los programas incluyen repeticiones o ciclos. Los bucles son
estructuras que permiten ejecutar partes del código de forma repetida mientras se
cumpla una condición.

Esta condición puede ser simple o compuesta de otras condiciones unidas por
operadores lógicos. Según cómo queramos que se controle ese bucle, tenemos tres

posibilidades, que básicamene se pueden describir como:

for: La orden se repite desde que una variable tiene un valor inicial hasta
que alcanza otro valor final.

while: Repite una sentencia mientras que sea cierta la condición que in-
dicamos. La condición se comprueba antes de realizar la sentencia.

do..while: Igual, pero la condición se comprueba después de realizar la sen-


tencia.

Las diferencias son: for normalmente se usa para algo que se repite un número
fijo de veces, mientras que "while"se basa en comprobar si una condición es cierta,
se repetirá un número mienstras se cumpla la condición.

4.1. Instrucción FOR


Su sintaxis es:

for (inicialización;condición;incremento)
{

37
38 Gustavo A. Yarce

sentencia1;
sentencia2;
}

La inicialización indica una variable (variable de control) que condiciona( 3.1)


la repetición del bucle. Si hay más, van separadas por comas:

Ejemplo 4.1
/* Uso de la sentencia FOR. */

#include <stdio.h>
#include <conio2.h>

main() /* Escribe la tabla de multiplicar */


{
int num,x,result;
printf("Introduce un número: ");
scanf("%d",&num);
for (x=0;x<=10;x++)
{
result=num*x;
printf("\n%d por %d = %d\n",num,x,result);
}
getch();
}

Pueden utilizarse dos condiciones en un bucle

for(Inicialización1,inicialización2;condición1,condición2;incremento1,incremento2)

El programa sigue avanzando,no se sale del bucle for, hasta que se cumplen las
dos condiciones.

4.2. Instrucción WHILE


Con esta sentencia se controla la condición antes de entrar en el bucle. Si ésta
no se cumple, el programa no entrará en el bucle.
Naturalmente, si en el interior del bucle hay más de una sentencia, éstas deberán
Laboratorio de Computadoras 39

ir entre llaves para que se ejecuten como un bloque.


Su sintaxis es:

while (condición) sentencia;

Ejemplo 4.2
/* Uso de la sentencia WHILE. */

#include <stdio.h>
#include <conio2.h>

main() /* Escribe los números del 1 al 10 */


{
int numero=1;
while(numero<=10)
{
printf("%d\n",numero);
numero++;
}
getch();
}

4.3. Instrucción DO...WHILE


Con esta sentencia se controla la condición al final del bucle. Si ésta se cumple,
el programa vuelve a ejecutar las sentencias del bucle.
La única diferencia entre las sentencias while y do...while es que con la segunda el
cuerpo del bucle se ejecutará por lo menos una vez. Su sintaxis es:

do{
sentencia1;
sentencia2;
}while (condición);

Ejemplo 4.3
/* Uso de la sentencia DO...WHILE. */
40 Gustavo A. Yarce

#include <stdio.h>
#include <conio2.h>

main() /* Muestra un menú si no se pulsa 4 */


{
char seleccion;
do{
printf("1.- Comenzar\n");
printf("2.- Abrir\n");
printf("3.- Grabar\n");
printf("4.- Salir\n");
printf("Escoge una opción: ");
seleccion=getchar();
switch(seleccion){
case ’1’:printf("Opción 1");
break;
case ’2’:printf("Opción 2");
break;
case ’3’:printf("Opción 3");
}

}while(seleccion!=’4’);
}
Capítulo 5

Funciones

La programación estructurada trata de dividir el programa en bloques más


pequeños, buscando una mayor legibilidad, y más comodidad a la hora de corregir
o ampliar.
La idea es que un programa que cumpla una cierta misión tendrá que seguir
ciertos pasos. Por ejemplo: para resolver un sistema de ecuaciones, los pasos po-
drían ser:
Pedir Número de Ecuaciones y de Incógnitas.
Para cada ecuación:
• Pedir coeficientes de x(i).
• Pedir término independiente.
Escribir el sistema como matriz.
Hacer ceros bajo la diagonal principal.
Aplicar sustitución regresiva.
Mostrar resultados.
Esos son los pasos que uno piensa cuando se plantea cómo resolver el problema
(el “algoritmo”), pensamos en “cosas a hacer”, no en líneas de programa, por eso la
forma más “natural” de trabajar es descomponer el problema en partes, en vez de
intentar resolverlo tecleando una línea tras otra.
Es la clásica idea del “divide y vencerás”: un programa que hayamos dividido
en bloques (con una cierta conexión, no a lo loco) será más fácil de crear y de
mantener.
En muchos lenguajes de programación, como Pascal, estos bloques son de dos
tipos: procedimientos (“procedure”) y funciones (“function”).

41
42 Gustavo A. Yarce

La diferencia entre ellos es que un procedimiento ejecuta una serie de acciones


que están relacionadas entre sí, y no devuelve ningún valor, mientras que la función
sí que va a devolver valores.
Por ejemplo, un procedimiento podría saludarnos: realizar una determinada
cantidad de instrucciones, muestra un mensaje en pantalla y terminar.

Saluda;

Por el contrario una función podría ser la raíz cuadrada: realizar una determina-
da cantidad de instrucciones, destinados a calcular cual es el valor, pero finalmente
tiene que respondernos diciendo qué valor ha obtenido.

x = Raiz(9); (y el ordenador debe “devolverme” el número: 3)

En C sólo existen funciones, pero éstas pueden devolver unos valores de tipo
“nulo”, con lo cual equivale a un procedimiento.

Su sintaxis es:

"tipo función" "nombre función" (tipo y nombre de argumentos)


{
bloque de sentencias
}

tipo función: puede ser de cualquier tipo de los que conocemos. El valor
devuelto por la función será de este tipo. Por defecto, es decir, si no indicamos
el tipo, la función devolverá un valor de tipo entero (int). Si no queremos
que retorne ningún valor deberemos indicar el tipo vacío (void).

nombre función: es el nombre que le daremos a la función.

tipo y nombre de argumentos: son los parámetros que recibe la función. Los
argumentos de una función no son más que variables locales que reciben un
valor. Este valor se lo enviamos al hacer la llamada a la función. Pueden
existir funciones que no reciban argumentos.

bloque de sentencias: es el conjunto de sentencias que serán ejecutadas cuan-


do se realice la llamada a la función.

Las funciones pueden ser llamadas desde la función main o desde otras fun-
ciones. Nunca se debe llamar a la función main desde otro lugar del programa.
Por último recalcar que los argumentos de la función y sus variables locales se
destruirán al finalizar la ejecución de la misma.
Laboratorio de Computadoras 43

Ejemplo 5.1
#include <stdio.h>
#include <conio.h>

int potencia(int base, int exponente)


{
int temporal = 1; /* Valor que voy hallando */
int i; /* Para bucles */

for(i=1; i<=exponente; i++) /* Multiplico "n" veces */


temporal =temporal*base; /* Y calculo el valor temporal */

return temporal; /* Al final de las multiplicaciones, */


} /* obtengo el valor que buscaba */

main()
{
int num1, num2;

printf("Introduzca la base: ");


scanf("%d", &num1);
printf("Introduzca el exponente: ");
scanf("%d", &num2);
printf("%d elevado a %d vale %d", num1, num2, potencia(num1,num2));
getch();
}

base y exponente son dos valores que se “le pasan” a la función: son sus
“parámetros”, unos datos que la función necesita. En nuestro caso, queremos
elevar un número a otro, luego deberemos indicarle cual es el número que
queremos elevar (la base) y a qué número lo queremos elevar (el exponente).

El cuerpo de la función se indica entre llaves, como cualquier otro bloque de


un programa.

i y temporal son variables locales a la función “potencia”: no se puede ac-


ceder a ellas desde ninguna otra parte del programa. Igual ocurre con num1
y num2: sólo se pueden leer o modificar desde “main”. Las variables que
habíamos visto hasta ahora no estaban dentro de ninguna función, por lo
44 Gustavo A. Yarce

que eran globales a todo el programa. Un detalle importante: las variables


locales se deberán declarar al principio de la función, antes de que aparezca
ninguna orden.

Con “return” salimos de la función e indicamos el valor que queremos que


se devuelva. En este caso es lo que habíamos llamado “temporal”, que era el
valor que íbamos calculando para la potencia en cada paso. Si no queremos
que retorne ningún valor deberemos indicar el tipo vacio (void).

Ejemplo 5.2
#include <stdio.h>
#include <conio.h>

void saludo(char nombre[])


{
printf("Hola %s ", nombre);
}

main()
{
saludo("Eva");
printf("\n");
getch();
}

Esta función es de tipo “void” (nulo), con lo que indicamos que no queremos
que devuelva ningún valor.

“char nombre[]” indicamos que le vamos a pasar una cadena de caracteres,


pero no hace falta que digamos su tamaño. Así podremos pasar cadenas de
caracteres tan grandes (o tan pequeñas) como queramos.

Esta función no termina en “return”, porque no queremos que devuelva


ningún valor.

Tenemos que “main” es una función, de tipo entero (se considera así si no se
indica el tipo, que es lo que estábamos haciendo hasta ahora), por lo que, podemos
escribir de otra forma el ejemplo de la potencia, sería:

Ejemplo 5.3
#include <stdio.h>
Laboratorio de Computadoras 45

#include <conio.h>

int potencia(int base, int exponente)


{
int temporal = 1; /* Valor que voy hallando */
int i; /* Para bucles */

for(i=1; i<=exponente; i++) /* Multiplico "n" veces */


temporal =temporal*base; /* Y calculo el valor temporal */

return temporal; /* Al final de las multiplicaciones, */


} /* obtengo el valor que buscaba */

int main()
{
int num1, num2;

printf("Introduzca la base: ");


scanf("%d", &num1);
printf("Introduzca el exponente: ");
scanf("%d", &num2);
printf("%d elevado a %d vale %d", num1, num2, potencia(num1,num2));
getch();
return 0;
}

Las funciones pueden declararse antes de la función “main” y luego escribir el


cuerpo de la función en otro lugar.

Ejemplo 5.4
#include <stdio.h>
#include <conio.h>

void funcion(void); /* declaración de la función */

int num=5; /* variable global */


46 Gustavo A. Yarce

main() /* Escribe dos números */


{
int num=10; /* variable local */
printf("%d este valor corresponde a una variable local \n",num);
funcion(); /* llamada */
getch();
}

/*Cuerpo de la función*/
void funcion(void)
{
printf("%d este valor corresponde a una variable global \n",num);
}

En el ejemplo podemos ver la declaración de una función . Al no recibir ni


retornar ningún valor, está declarada como “void” en ambos lados. También vemos
que existe una variable global llamada num. Esta variable es reconocible en todas
las funciones del programa. Ya en la función main encontramos una variable local
llamada num. Al ser una variable local, ésta tendrá preferencia sobre la global. Por
tanto la función escribirá los números 10 y 5.

Las funciones también pueden ser escritas en otro archivo. En este caso se lo
indicaremos al compilador mediante la directiva “#include”.

Ejemplo 5.5
#include <stdio.h>
#include <conio.h>
#include <c:\potencia.cpp>

main()
{
int num1, num2;

printf("Introduzca la base: ");


scanf("%d", &num1);
printf("Introduzca el exponente: ");
scanf("%d", &num2);
printf("%d elevado a %d vale %d", num1, num2, potencia(num1,num2));
getch();
Laboratorio de Computadoras 47

5.1. Paso de parámetros a una función


Como ya hemos visto, las funciones pueden retornar un valor. Esto se hace
mediante la instrucción return, que finaliza la ejecución de la función, devolviendo
o no un valor.

En una misma función podemos tener más de una instrucción return. La forma
de retornar un valor es la siguiente:

return ( valor o expresión );

El valor devuelto por la función debe asignarse a una variable. De lo contrario,


el valor se perderá.
En el ejemplo puedes ver lo que ocurre si no guardamos el valor en una variable.
Fíjate que a la hora de mostrar el resultado de la suma, en el printf, también
podemos llamar a la función.

Ejemplo 5.6
#include <stdio.h>
#include <conio.h>

int suma(int a,int b)


{
return (a+b);
}

main() /* Realiza una suma */


{
int a=10,b=25,t;
t=suma(a,b); /* guardamos el valor */
printf("%d=%d",suma(a,b),t);
suma(a,b); /* el valor se pierde */
getch();
}

Paso de parámetros.
48 Gustavo A. Yarce

Existen dos formas de enviar parámetros a una función:

Por valor: cualquier cambio que se realice dentro de la función en el argu-


mento enviado, NO afectará al valor original de las variables utilizadas en la
llamada. Es como si trabajaramos con una copia, no con el original. No es
posible enviar por valor arrays, deberemos hacerlo por referencia.

Por referencia: lo que hacemos es enviar a la función la dirección de memoria


donde se encuentra la variable o dato. Cualquier modificación SI afectará
a las variables utilizadas en la llamada. Trabajamos directamente con el
original.

Ejemplo 5.7

#include <stdio.h>
#include <conio.h>

void intercambio (int x,int y)


{
int aux;
aux=x;
x=y;
y=aux;
printf("a=%d y b=%d",x,y);
}

main() /* Intercambio de valores */


{
int a=1,b=2;
printf("a=%d y b=%d",a,b);
intercambio(a,b); /* llamada */
printf("a=%d y b=%d",a,b);
getch();
}

Para enviar un valor por referencia se utiliza el símbolo & ( ampersand ) delante
de la variable enviada. Esto le indica al compilador que la función que se ejecutará
tendra que obtener la dirección de memoria en que se encuentra la variable.
Laboratorio de Computadoras 49

Vamos a fijarnos en los ejemplos. En el ejemplo anterior podrás comprobar


que antes y después de la llamada, las variables mantienen su valor. Solamente se
modifica en la función intercambio ( paso por valor ).
En el siguiente ejemplo podrás ver como las variables intercambian su valor
tras la llamada de la función ( paso por referencia ).
Las variables con un “*” son conocidas como punteros, el único dato en “C” que
puede almacenar una dirección de memoria.

Ejemplo 5.8

/* Paso por referencia. */

#include <stdio.h>
#include <conio.h>

void intercambio (int *x,int *y)


{
int aux;
aux=*x;
*x=*y;
*y=aux;
printf("a=%d y b=%d",*x,*y);
}

main() /* Intercambio de valores */


{
int a=1,b=2;
printf("a=%d y b=%d",a,b);
intercambio(&a,&b); /* llamada */
printf("a=%d y b=%d",a,b);
getch();
}

Recursividad
La idea es simplemente que una función recursiva es aquella que se llama a sí
misma. El ejemplo clásico es el factorial de un número:
50 Gustavo A. Yarce

Partimos de la definición de factorial: el factorial de un número es

n! = n (n-1) (n-2) ... 3 2 1

Por otra parte, el factorial n-1 es

(n-1)! = (n-1) (n-2) (n-3) ... 3 2 1

Luego podemos escribir cada factorial en función del factorial del siguiente
número:

n! = n (n-1)!

Pues esta es la definición recursiva del factorial, ni más ni menos. Esto, pro-
gramando, se haría:

Ejemplo 5.9
#include <stdio.h>
#include <conio.h>

long fact(int n)
{
if (n==1) /* Aseguramos que termine */
return 1;
return n * fact (n-1); /* Si no es 1, sigue la recursión */
}

main()
{
int num;
printf("Introduzca un número entero: ");
scanf("%d", &num);
printf("Su factorial es: %ld\n", fact(num));
getch();
}
Capítulo 6

Arrays

6.1. Vectores
Vectores
Un vector es un array unidimensional, es decir, sólo utiliza un índice para
referenciar a cada uno de los elementos. Su declaración será:

tipo nombre [tamaño];

El tipo puede ser cualquiera de los ya conocidos y el tamaño indica el número


de elementos del vector ( se debe indicar entre corchetes [ ] ).
El primer elemento de cualquier vector es el elemento cero. En el ejemplo puedes
observar que la variable i es utilizada como índice, el primer for sirve para rellenar
el vector y el segundo para visualizarlo. Como ves, las posiciones van de 0 a 9 (
total 10 elementos ).
Podemos inicializar (asignarle valores) un vector en el momento de declararlo.
Si lo hacemos así no es necesario indicar el tamaño. Su sintaxis es:

tipo nombre []={ valor 1, valor 2...}

Ejemplos:

int vector[]={1,2,3,4,5,6,7,8};
char vector[]="programador";
char vector[]={’p’,’r’,’o’,’g’,’r’,’a’,’m’,’a’,’d’,’o’,’r’};

Una particularidad con los vectores de tipo char (cadena de caracteres), es


que deberemos indicar en que elemento se encuentra el fin de la cadena mediante
el caracter nulo ( \ 0 ). Esto no lo controla el compilador, y tendremos que ser
nosotros los que insertemos este caracter al final de la cadena.

51
52 Gustavo A. Yarce

Por tanto, en un vector de 10 elementos de tipo char podremos rellenar un


máximo de 9, es decir, hasta vector[8]. Si sólo rellenamos los 5 primeros, hasta
vector[4], debemos asignar el caracter nulo a vector[5]. Es muy sencillo: vector[5]=
’\0’.
Ahora veremos un ejemplo de como se rellena un vector de tipo char.

Ejemplo 6.1
/* Declaración de un array. */

#include <stdio.h>
#include <conio2.h>

main() /* Rellenamos del 0 - 9 */


{
int vector[10],i;
for (i=0;i<10;i++) vector[i]=i;
for (i=0;i<10;i++)
{
printf(" %d",vector[i]);
}
getch();
}

6.2. Operaciones
Las principales operaciones que se pueden realizar son:

Acceso: cada elemento de un array se nombra con el identificador del array


al que perteneces seguido de su posición entre corchetes [n-1]. Es decir, si en
un array[10], queremos nombrar la 4 posición, esta sería array[3]. La posición
de comienzo de un array es la 0.

Asignación: normalmente para asignar valores a un array utilizamos un bucle


for, aunque los bucle do while y while también pueden utilizarse.

Iniciación: a un array le podemos dar valores iniciales, para ello se declararía


de la siguiente forma:
(Donde lista de valores es una lista de constante separadas por comas)
Laboratorio de Computadoras 53

Tipo nombre_array[tamaño]={lista_valores};

int lista[6]={2,4,6,8,1,5};

int datos[100]={0}; // todos se inicializan a 0

int num[4]={4,5}; // equivale a {4,5,0,0}

6.3. Múltiples dimensiones


Se pueden declarar matrices de dos o más dimensiones, según esta sintaxis:

tipo matriz [ dimensión1 ] [ dimensión2 ] ... ;

Ejemplo 6.2
#include <stdio.h>
#include <conio.h>
main() /* Rellenamos una matriz */
{
int x,i,numeros[3][4];
/* rellenamos la matriz */
for (x=0;x<3;x++)
for (i=0;i<4;i++)
scanf("%d",&numeros[x][i]);
/* visualizamos la matriz */
for (x=0;x<3;x++)
for (i=0;i<4;i++)
printf("%d",numeros[x][i]);
}

6.4. Paso de parámetros a una función


Para pasar cualquier argumento a una función, especifique el nombre del ar-
reglo, sin corchete alguno. Por ejemplo:

int temp[20]
54 Gustavo A. Yarce

la llamada a la función se haría como:

funcionvector(temp,20);

la función tendrá en su encabezado

void funcionvector(int temper[], int n)

En este ejemplo se pasa el arreglo a la función y el tamaño del mismo. Cabe


mencionar que la función no puede devolver como valor un vector.

Para modificar el valor de un arreglo con una función y que el valor modificado
pueda ser utilizado posteriormente fuera de la función se debe realizar lo siguiente:

nombre_de_la_función( & nombre_del_arreglo [0]);

int temp[20]

la llamada a la función se haría como:

funcionvector(&temp[0],20);

la función tendrá en su encabezado

void funcionvector(int temper[], int n)


Capítulo 7

Gráficos

7.1. Librería WinbGim


“Winbgim.h” es una libreria de C++ que tiene como objetivo emular la librería
graphics.h de Borland C++. Una de las ventajas de esta librería es que nos permite
crear aplicaciones gráficas con compiladores GNU tales como el “Dev C++”.

Con el fin de facilitar el uso de esta librería se dispone de un instalador para


la versión 4.9.9.2 del Dev C++ que realiza todas las configuraciones necesarias.

Una vez realizada la instalación es necesario reiniciar la PC para que las mod-
ificaciones sean actualizadas. Se debe realizar al igual que la librería Conio la
siguiente modificación en el compilador, en “Herramientas” - “Opciones del compi-
lador” - “Añadir estos comandos...”:

-lbgi -lgdi32 -luser32

junto a la opción de la librería Conio -lconio, resultando en:

-lconio -lbgi -lgdi32 -luser32

55
56 Gustavo A. Yarce

7.2. Instrucciones
7.2.1. initwindow
Esta función inicializa el modo gráfico, creando una ventana del tamaño especi-
ficado. Los parámetros obligatorios de esta función son los dos primeros, ancho y
alto, ambos valores son enteros. Esta instrucción se complementa con la instrucción
“closegraph()”, la cual cierra el modo gráfico.

Ejemplo 7.1
#include <winbgim.h>
#include <conio.h>

main()
{

initwindow(400,300); // Abre una ventana gráfica de 400x300 pixeles

getch();
closegraph(); // Cierra la ventana gráfica
}

7.2.2. getmaxx
Retorna la coordenada máxima horizontal.
int xmax;

xmax=getmaxx();

7.2.3. getmaxy
Retorna la coordenada máxima vertical.
int ymax;

ymax=getmaxy();
Laboratorio de Computadoras 57

7.2.4. moveto
Se mueve a las coordenadas indicadas

moveto(50,40);

7.2.5. setcolor
Selecciona el color de dibujo y texto indicado. Ej: setcolor(1);

7.2.6. setbkcolor
Selecciona el color de fondo indicado. Ej: setbkcolor(4);

7.2.7. cleardevice
Borra la pantalla. Ej: cleardevice( );

7.3. funciones de dibujo


7.3.1. putpixel
putpixel(int x , int y , color);

Grafica un pixel en las coordenadas y color indicados. Ej: putpixel(100,50,9);

7.3.2. line
line(int x1 , int y1 , int x2 , int y2);

Dibuja una linea desde x1,y1 a x2,y2. Ej: line(20,10,150,100);


58 Gustavo A. Yarce

7.3.3. lineto
lineto(int x1 , int y1);

Dibuja una linea desde el último que se graficó hasta el x1,y1

moveto(0,0)
lineto(400 , 400); //traza una diagonal en la pantalla

7.3.4. circle
circle(int x , int y , int radio);

Dibuja un círculo del radio indicado y con centro en x,y. Ej: circle(320,200,20);

7.3.5. rectangle
rectangle(int x1 , int y1 , int x2 , int y2);

Dibuja un rectángulo con la esquina superior izquierda en x1,y1 y la inferior


derecha en x2,y2. Ej: rectangle(280,210,360,270);

7.4. Funciones de escritura de texto


7.4.1. outtextxy
outtextxy(int x , int y , char *);

Muestra el texto indicado en las coordenadas x,y. Ej: outtextxy(50,50,“Esto es


texto en modo gráfico”);

7.4.2. settextstyle
settextstyle(int fuente , int dirección , int tamaño);

Selecciona el estilo del texto. Las fuentes más comunes son las que van de 0 a
4. La dirección puede ser: 0 = horizontal y 1 = vertical. El tamaño puede tomar
un valor de 1 a 10. Ej: settextstyle(2,0,5);
Capítulo 8

Cadenas de texto

8.1. Introducción
Una cadena de texto en C no es más que un array de caracteres. Como a todo
array, se le puede reservar espacio. Esto es de la siguiente forma:

char texto[80];

En cualquier caso, una cadena de caracteres siempre terminará con un carácter


nulo (\0). Por eso, si necesitamos 7 letras para un teléfono, deberemos hacer

char telefono[8];

dado que hay que almacenar esas 7 y después un “\0”. Si sabemos lo que
hacemos, podemos reservar sólo esas 7, pero tendremos que usar nuestras propias
funciones, porque las que nos ofrece el lenguaje C se apoyan todas en que al final
debe existir ese carácter nulo.

8.2. Comandos
Para copiar el valor de una cadena de texto en otra, no podemos hacer

texto1 = texto2;

porque estaríamos igualando dos punteros. A partir de este momento, las dos
cadenas se encontrarían en la misma posición de memoria, y los cambios que
hiciéramos en una se reflejarían también en la otra.

Se debe usar una función de biblioteca, “strcpy” (string copy), que se encuen-
tra, como todas las que veremos, en “string.h”:

59
60 Gustavo A. Yarce

strcpy (destino, origen);


Es nuestra responsabilidad que en la cadena de destino haya suficiente espacio
reservado para copiar lo que queremos. Si no es así, estaremos sobreescribiendo
direcciones de memoria en las que no sabemos qué hay.

Si queremos copiar sólo los primeros n bytes de origen, usamos


strncpy (destino, origen, n);

Para añadir una cadena al final de otra (concatenarla), usamos


strcat (origen, destino);

Para comparar dos cadenas alfabéticamente (para ver si son iguales o para
poder ordenarlas, por ejemplo), usamos
strcmp (cad1, cad2);
Esta función devuelve un número entero, que será:
“0” si ambas cadenas son iguales
negativo, si cad1 < cad2
positivo, si cad1 > cad2

La llamada “gets(cad)” lee todos los caracteres hasta encontrar el final de


línea “\n”, que en la cadena “cad” se sustituye por “\0”

gets (cad);
La llamada “getch()” puede ser utilizada para leer un carácter tecleado. Este
carácter no se visualiza en pantalla

gets (cad);

La llamada “toupper(caracter)” cambia el carácter de minúscula a mayus-


culas. Se debe utilizar la librería “ctype”.

La llamada “lower(caracter)” cambia el carácter de mayusculas a minúscula.

La llamada “strlen(cadena)” devuelve la longitud de la cadena.


Capítulo 9

Punteros

9.1. Introducción
Hasta ahora teníamos una serie de variables que declaramos al principio del
programa o de cada función. Estas variables, que reciben el nombre de ESTÁTI-
CAS, tienen un tamaño asignado desde el momento en que se crea el programa.
Este tipo de variables son sencillas de usar y rápidas, si sólo vamos a manejar
estructuras de datos que no cambien, pero resultan poco eficientes si tenemos
estructuras cuyo tamaño no sea siempre el mismo.
Es el caso de un vector: tenemos una serie de valores, e iremos añadiendo más.
Si reservamos espacio para 10, no podremos llegar a añadir la número 11, estamos
limitando el máximo. Una solución sería la de trabajar siempre en el disco: no
tenemos límite en cuanto a número de valores, pero es muchísimo más lento.
Lo ideal sería aprovechar mejor la memoria que tenemos en el ordenador, para
guardar en ella todas las fichas o al menos todas aquellas que quepan en memoria.
Una solución “típica” (pero mala) es sobredimensionar: preparar un vector con-
tando con 1000 valores, aunque supongamos que no vamos a pasar de 200. Esto
tiene varios inconvenientes: se desperdicia memoria, obliga a conocer bien los datos
con los que vamos a trabajar, sigue pudiendo verse sobrepasado, etc.

La solución suele ser crear estructuras DINÁMICAS, que puedan ir creciendo


o disminuyendo según nos interesen. Ejemplos de este tipo de estructuras son:

Las pilas. Justo como una pila de libros: vamos apilando cosas en la cima, o
quitando de la cima.

Las colas. Como las del cine, por ejemplo (en teoría): la gente llega por un
sitio (la cola) y sale por el opuesto (la cabeza).

61
62 Gustavo A. Yarce

Las listas, en las que se puede añadir elementos, consultarlos o borrarlos en


cualquier posición.

Todas estas estructuras tienen en común que, si se programan bien, pueden ir


creciendo o decreciendo según haga falta, al contrario que un array, que tiene su
tamaño prefijado.
En todas ellas, lo que vamos haciendo es reservar un poco de memoria para
cada nuevo elemento que nos haga falta, y enlazarlo a los que ya teníamos. Cuando
queramos borrar un elemento, enlazamos el anterior a él con el posterior a él (si
hace falta, para que no “se rompa”) y liberamos la memoria que estaba ocupando.
Así que para seguir, necesitamos saber cómo reservar memoria y cómo liberarla.

9.2. Punteros
Los punteros, son aquellos que como su nombre lo dice almacenan un espacio en
la memoria virtual dinamicamente, o sea mientras no sea creada la variable dentro
del programa, el espacio en la memoria volatil esta libre.Esta variable contiene la
dirección de memoria de otra variable. Se utilizan para pasar información entre
una función y sus puntos de llamada.

9.2.1. Declaración
Su sintaxis es la siguiente:

tipo *nombre;

Donde nombre es, naturalmente, el nombre de la variable, y tipo es el tipo del


elemento cuya dirección almacena el puntero.

9.2.2. Operadores
Existen dos operadores especiales para trabajar con punteros: & y *.
El primero devuelve la dirección de memoria de su operando. Por ejemplo, si
queremos guardar en el puntero x la dirección de memoria de la variable num,
deberemos hacer lo siguiente:

x= &num;
Laboratorio de Computadoras 63

El segundo devuelve el valor de la variable cuya dirección es contenida por el


puntero. Este ejemplo sitúa el contenido de la variable apuntada por x, es decir
num, en la variable a:

a=*x;

Ejemplo 9.1 int num; "num" es un número entero


int *pos; "pos" es un "puntero a entero" (dirección de
memoria en la que podremos guardar un entero)

num = 1; ahora "num" vale 1


pos = 1000; "pos" ahora es la dirección 1000 (peligroso)
*pos = 25; en la posición "pos" guardamos un 25
pos = &num; "pos" ahora es la dirección de "num"

Por tanto, con el símbolo * indicamos que se trata de un puntero, y & nos
devuelve la dirección de memoria en la que se encuentra una variable.
Lo de “pos=1000” es peligroso, porque no sabemos qué hay en esa dirección,
de modo que si escribimos allí podemos provocar una catástrofe. Por ejemplo, si
ponemos un valor al azar que coincide con la instrucción en código máquina de
formatear el disco duro, no nos hará nada de gracia cuando nuestro programa
llegue hasta esa instrucción. Normalmente las consecuencias no son tan graves,
pero hay que llevar cuidado. La forma de trabajar será pedir al compilador que
nos reserve un poco de memoria donde él crea adecuado
Para eso usamos la orden “malloc” (necesitaremos incluir en la cabecera <
stdlib.h >). Una vez que hemos terminado de usar esa memoria, suele ser conve-
niente liberarla, y para eso empleamos “free”.
“free(pos)” quiere decir “libera la memoria que ocupaba pos”. El de “malloc” es
más rebuscado:

malloc (tamaño)

Como queremos reservar espacio para un entero, ese “tamaño” será lo que ocupe
un entero, y eso nos lo dice “sizeof(int)”.
¿Y eso de (int*)? Es porque “malloc” nos devuelve un puntero sin tipo (un
puntero a void (void*). Cómo queremos guardar un dato entero, primero debemos
hacer una conversión de tipos (typecast), de “puntero sin tipo” a “puntero a entero”
(int *).
64 Gustavo A. Yarce

9.3. Asignación
Los punteros se asignan igual que el resto de las variables. El programa ejem-
plo mostrará las direcciones contenidas en p1 y p2, que será la misma en ambos
punteros.

Ejemplo 9.2
#include <stdio.h>
#include <stdlib.h>

main() /* Asignamos direcciones */


{
int a;
int *p1,*p2;
p1=&a;
p2=p1;
printf("%p %p",p1,p2);
system("PAUSE");
}

9.4. Aritmética de direcciones


Es posible desplazar un puntero recorriendo posiciones de memoria. Para ello
podemos usar los operadores de suma, resta, incremento y decremento (+, -, ++, - -
). Si tenemos un puntero ( p1 ) de tipo int ( 2 bytes ), apuntando a la posición 30000
y hacemos: p1=p1+5; el puntero almacenará la posición 30010, porque apunta 5
enteros por encima ( 10 bytes más ).
====================================================

Você também pode gostar