Você está na página 1de 67

Programacin en C

Prlogo
El avance de la tecnologa y la concurrente entrega de informacin, nos permite generar una
edicin, variable y alternativa en la enseanza del lenguaje de programacin que ms impacto
social ha tenido en la historia de la informtica. Este libro ha sido forjado con la incansable
ayuda de informticos de habla hispana, quienes byte a byte han colaborado por hacer de la
informacin una fuente de conocimiento global. De la misma forma, contina hoy siendo
modificado en una constante bsqueda de superacin de la calidad.
Esta obra est llamada a ser la piedra angular en la enseanza de la programacin, logrando
abarcar todos los aspectos del lenguaje en diversos niveles y de esta forma ser tanto una
referencia tcnica para quienes ya dominan el lenguaje como una introduccin sencilla para
quienes estn empezando a conocerlo.
Viajaremos por la historia del lenguaje, veremos su propsito e indagaremos en la ciencia de la
programacin. El fin es otorgar al lector una doctrina clara de la programacin y el lenguaje C;
lo induciremos a conseguir un manejo importante del lenguaje.
Para quin es este libro?
Este libro est dirigido a todos los que deseen obtener conocimientos de programacin, pues el
objetivo explcito que nos ha motivado a crearlo es difundir la importancia del lenguaje C en el
mundo de la informtica. Si nos enfocamos a un grupo social especfico, podremos indicar que
este libro contribuir con los estudiantes de carreras del rea informtica, debido a que los
temas convenidos, son parte de su plan de estudios.

Por qu otro manual de C?
Porque el lenguaje C es la base fundamental de la programacin. Para quienes estn en el
ambiente de la informtica es crucial tener por lo menos nociones de este lenguaje. Varios
sistemas operativos, cientos de bibliotecas, y miles de programas estn construidos utilizando
C, al conocerlo es posible entender, colaborar y desarrollar en este lenguaje.
Los sistemas, programas, juegos y herramientas que nosotros disfrutamos hoy fueron
construidos por personas como nosotros, que empezaron con nuestro mismo potencial y
fueron aprendiendo a hacer cosas fantsticas con las herramientas que tenan a mano.
Una razn importante para otro libro de lenguaje C es tambin que los libros existentes
muestran muy poca documentacin de calidad. En Internet existe una cantidad inmensa de
informacin publicada pero est dispersa, y mal manejada en algunos sitios. Es la intencin de
este libro crear un buen compendio de informacin, que permita a los interesados aprender a
programar en C.

Enlaces
Nociones bsicas de programacin (generales, independientes del lenguaje):
Fundamentos de programacin
Wikilibro similar a ste en ingls
C Programming
esquema de operadores y expresiones
[1]
Licencia y autores
Copyright 2004 Envite
Copyright 2005 Alejandro Moreno Calvo
Copyright 2006 Andreu Correa Casablanca
Copyright 2009 zerohours
Ver el historial de cada pgina para el resto de autores.
Cmo contribuir a este WikiLibro?
Contribuir con este libro es muy simple primero deberas registrarte un usuario y/o entrar (esto
no es necesario pero si muy conveniente) a Wikilibros, para que podamos identificar tus
ediciones. Luego, si nunca has contribuido en un proyecto de wikipedia o en otro wiki deberas
leer el manual de uso de wikilibros.
Una vez hecho esto todo lo que tienes que hacer es agregar el contenido que consideres
necesario para el libro. Para editar cualquier seccin basta con hacer click al link que
dice editaren la pestaa en la parte superior de la pagina, seria bueno revisar (antes de editar
cualquier cosa) la pestaa de discusin que est ah para ser usada. Ten en cuenta que el
material que ya est fue escrito por personas que deseaban contribuir igual que t, as que
trata de respetarlo. Aunque con esto no me refiero a que si se necesita alguna correccin,
reorganizacin, quitar partes que sean ambiguas, no dejes de hacerlo. Lo mejor sera que todos
contribuyramos de cualquier manera al libro.
Adems, es recomendable consultar la pgina de discusin del libro y la del articulo en
particular que quieras modificar, ya que de esta manera se pueden coordinar esfuerzos.
Recuerda que todo el contenido que aadas al libro es publicado bajo la licencia GFDL, por lo
que no uses material que no haya sido escrito por ti o que no est ya publicado bajo GFDL.
Recientemente wikimedia decidi adoptar la Licencia Creative Commons Compartir-Igual
3.0 para todos los aportes, por lo que actualmente el libro tiene una licencia dual.
Introduccin
Objetivos
El objetivo principal de este Wikilibro es que cualquier persona sin conocimientos previos de
programacin pueda ser capaz de programar en el lenguaje C.
Una vez logrado el dominio del lenguaje, es probable que los lectores se interesen por otros
temas ms complejos que superen a los temas bsicos. Tambin les ser ms o menos sencillo
aprender cualquier otro lenguaje de programacin estructurada.
Sin embargo, este no es un libro que apunte nicamente a programadores principiantes.
Tambin puede resultar de inters para quienes ya tengan experiencia en el rea de
programacin. En esta introduccin hay dos secciones en las que se explica para los dos grupos
principales de lectores qu camino seguir para comenzar a programar en el lenguaje C o bien
perfeccionar conocimientos.
El lenguaje C es tan usado porque es un lenguaje de programacin que emplea pocas
instrucciones en lenguaje mquina para traducir elementos del cdigo. Esto reduce los tiempos
de ejecucin de los programas.
Nota sobre la exactitud
Muchas de las cosas expresadas en este wikilibro, especialmente en los primeros captulos, no
son completamente exactas, aunque son buenas aproximaciones. Los detalles ms exactos irn
apareciendo posteriormente, una vez que los materiales anteriores hayan sido correctamente
asimilados por el lector. En general, dadas dos definiciones o datos contradictorios en este
wikilibro, debe considerarse siempre como ms exacto al segundo, habiendo aparecido el
primero como una introduccin ms general al tema.
Estndar utilizado
El lenguaje C fue creado en los aos setenta, y a lo largo de su historia ha pasado por muchas
modificaciones, tanto con respecto a la sintaxis como con respecto al cdigo incluido dentro de
la biblioteca estndar. Es por ello que se fueron desarrollando estndares, para que todos
sepan con qu versin del lenguaje se est trabajando.
Los distintos estndares del lenguaje C han sido: el C de Kernighan y Ritchie, un estndar no-
oficial que surgi luego de la publicacin de su libro en 1978; el C89 o C90, el primer estndar
oficial, posterior a la publicacin de los estndares ANSI en 1989 e ISO en 1990; y el C99,
publicado en 1999.
En este libro se utilizar el estndar C99, si bien por cuestiones de estilo y compatibilidad
muchas veces se utilizar cdigo compatible con el estndar C89.
Para los principiantes
Para quien no haya programado antes, es recomendable seguir el orden del libro. Los temas
estn especialmente organizados de manera incremental o acumulativa. Tal vez, lo que se te va
a hacer ms til en el camino del aprendizaje es la constancia; s terco, no trastabilles, no te
rindas, tal vez tu pregunta sea cuntas veces tengo que intentar?, las veces necesarias para
lograr tu objetivo, sera la respuesta.
Claro que el principal enemigo de nosotros los humanos es el tiempo y por eso en caso de que
de verdad ests trancado en algo busca ayuda de alguien que sepa "ms que t". Que no
tienes a nadie a tu alrededor con esa caracterstica? Tal vez no buscaste bien y tal vez quieras
usar la red de redes. Utiliza los buscadores, pregunta en IRC, en foros de programacin, en
listas de correo.
Para los ms avanzados
El lanzamiento queda libre por supuesto, solo t sabes lo que necesitas. Las reglas del juego
son las mismas de siempre: primero saber lo que se quiere o necesita y atacar por ah.
En este caso, te ser til acceder a los contenidos a partir del ndice, eligiendo slo aquellos que
te sean necesarios.
Requisitos
Se presupone que los lectores tienen conocimientos elementales de informtica a nivel de
usuario, y son capaces de instalar un compilador del lenguaje C en sus sistema. Los detalles
sobre la instalacin se vern en la seccin Herramientas.
Con respecto al Hardware, slo ser necesario contar con una PC con sistema operativo, donde
sea posible instalar un compilador, y en lo posible un entorno de desarrollo. Cuanto mejor sea
la computadora, ms rpido ser el proceso de compilacin y ejecucin de los programas. Sin
embargo, cualquier PC sirve para aprender con los ejemplos de este libro.
Para quienes no tengan conocimientos bsicos de programacin, puede ser una buena idea
comenzar leyendo los primeros captulos del Wikilibro Fundamentos de programacin, ya que
algunos temas explicados en ese libro se asumen ya conocidos.
Finalmente, un requisito imprescindible en todo programador o programadora es tener sentido
comn. Muchas veces se pueden adoptar mejores o peores soluciones ante los diversos
problemas, y la decisin de cul elegir pasa por la aplicacin del sentido comn. yapa
Herramientas
Para programar tanto en C, como en C++, Java o cualquier otro lenguaje de programacin,
necesitamos contar con aplicaciones o herramientas que nos permitan poner en
funcionamiento nuestro programa.
El lenguaje de programacin C es compilado, as que en este caso necesitaremos un compilador,
que ser el encargado de transformar nuestro cdigo fuente en cdigo que la computadora
pueda ejecutar.
Adems, para facilitar la tarea de los programadores existen los denominados Entorno de
desarrollo integrados (IDE). En muchos casos, estos entornos incluyen un compilador, un
depurador, y otras herramientas.
Las herramientas a instalar dependern del sistema operativo utilizado. A continuacin se listan
algunas posibilidades para el sistema operativo Windows o GNU/Linux, no es imprescindible
utilizar estas herramientas en particular, cualquier compilador puede servir.

Windows
Uno de los entornos de desarrollo ms conocidos entre los programadores de C
sobre Windows, tanto novatos como expertos, es el Bloodshed Dev-C++, que es un entorno
libre multiplataforma. Tal entorno de desarrollo fue abandonado y retomado mejorndolo
pasando a llamarse WxDev-C++. Otro entorno libre y gratuito es el Code::Blocks. Ambos
entornos pueden utilizarse tanto para C como para C++.
Tambin hay otras alternativas privativas como los compiladores de Borland o de Microsoft
(Microsoft Visual C++).
GNU/Linux
En los sistemas GNU/Linux, ser necesario tener instaladas las herramientas gcc y make y la
versin 6 de la glibc con su documentacin, que son las que permitirn compilar los programas.
Para escribir y modificar el cdigo, es posible utilizar cualquier editor de texto plano (en lo
posible que cuente con resaltado de sintaxis), como son emacs, vim, kate, gedit o geany.
Sin embargo, para quienes son novatos en la programacin, es recomendable utilizar un
entorno de desarrollo como son el Anjuta DevStudio (para el entorno GNOME) o KDevelop
(para el entorno KDE), ya que incluyen facilidades adicionales para la ejecucin y solucin de
problemas.
Los programas mencionados se incluyen dentro de la instalacin estndar de la mayora de las
distribuciones actuales de GNU/Linux, de modo que para instalarlos slo ser necesario seguir
el procedimiento usual de instalacin de aplicaciones para la distribucin deseada.


Historia de C
El lenguaje de programacin C fue creado por Dennis Ritchie entre 1969 y 1973 cuando
trabajaba en Bell Laboratories de AT&T junto con Ken Thompson en el diseo del sistema
operativo UNIX. C fue creado para poder escribir dicho sistema operativo en un lenguaje de alto
nivel, independiente del hardware donde se ejecutara.
Contar con un lenguaje de alto nivel permiti el avance de los sistemas operativos, ya que el
mismo cdigo poda ser utilizado en las distintas plataformas, propiciando la reutilizacin de
cdigo y reduciendo los tiempos de desarrollo. As es que los sistemas operativos basados en
UNIX, el sistema BSD, el sistema GNU/Linux y muchos otros fueron desarrollados en C.
Adems, con el paso del tiempo se han desarrollado cientos de bibliotecas que permiten a los
programadores de C utilizar el cdigo desarrollado por otros para la realizacin de tareas
comunes. Esto, a su vez, ha propiciado el desarrollo de aplicaciones en lenguaje C.
Actualmente es imposible contar la cantidad de aplicaciones y herramientas desarrolladas en C.
Evolucin
A mediados de los aos 60s, Martin Richards dise el lenguaje BCPL con la finalidad de usarlo
para escribir software de sistemas operativos y compiladores.
En 1969, Ken Thompson escribi el Lenguaje B, en Bell Laboratories, con el objetivo de
recodificar UNIX (escrito hasta ese momento en lenguaje ensamblador) usando un lenguaje de
alto nivel ms portable y flexible.
Durante los siguientes aos, Dennis Ritchie modific el lenguaje B, llegando a crear el lenguaje
C y reescribiendo el sistema UNIX en dicho lenguaje; aadi caractersticas nuevas, como son el
diseo de tipos y las estructuras de datos.
En 1978, Dennis Ritchie y Brian Kernighan publicaron la primera edicin del libro El lenguaje de
programacin C. Este libro fue durante aos la especificacin informal del lenguaje. El lenguaje
descrito en la primera edicin de este libro, fue conocido como "el C de Kernighan y Ritchie" o
simplemente "K&R C". En este libro se introdujeron nuevas caractersticas al lenguaje: los tipo
de datos struct, long int y unsigned int; los operadores =+ y =- fueron sustituidos por += y -=.
A mediados de los aos 80, Bjarne Stroustrup (tambin de los laboratorios Bell), crea
el lenguaje C++, un lenguaje basado en C, con numerosas caractersticas adicionales, siendo la
principal que est orientado a objetos. Si bien se han creado muchos lenguajes basados en C,
C++ es el que ha permanecido ms asociado a C.
En los aos siguientes a la publicacin del C de Kernighan y Ritchie, se aadieron al lenguaje
muchas caractersticas no oficiales, que estaban presentes en algunos compiladores y no en
otros. Fue por ello que en 1989 ANSI (American National Standards Institute) public el primer
estndar oficial de C, que es conocido como ANSI C.
En este estndar se tomaron muchas de las funcionalidades no oficiales y se agregaron
funcionalidades nuevas como los prototipos de funcin, y un preprocesador mejorado. Tambin
se cambi la sintaxis de la declaracin de parmetros de funciones, para que incluyeran el tipo
junto con el nombre.
Al ao siguiente, en 1990 se public la estandarizacin ISO del lenguaje. Este estndar es
bsicamente el estndar ANSI, con unas pocas modificaciones de formato. A este estndar se lo
conoce, entonces, como C89, o C90, y se trata del mismo lenguaje.
Basndose en el estndar ANSI que estaba en preparacin, en 1988 Kernighan y Ritchie
publicaron la segunda edicin de su libro, que es an hoy utilizada como una de las referencias
principales del lenguaje.
Durante los siguientes aos, el lenguaje C permaneci sin demasiados cambios. Sin embargo,
como haba sucedido antes, los distintos compiladores fueron incorporando caractersticas
adicionales, que otros compiladores no tenan, siendo C++ la principal influencia.
Fue por ello que a finales de los noventa se decidi revisar el estndar de C, lo que llev a la
publicacin del estndar C99. Este estndar incluye varias nuevas caractersticas como son: las
funciones inline; la posibilidad de declarar variables en cualquier parte del cdigo; los
comentarios de una sola lnea utilizando //; los tipos de datos long long int, bool y complex,
entre otras.
An hoy el proceso de evolucin del lenguaje sigue avanzando, y desde 2007 se est trabajando
en el armado de un nuevo estndar.
Ms informacin
Lenguaje de programacin BCPL
Historia del lenguaje del programacin C
The Development of the C Language

Fundamentos de programacin
En este captulo veremos un resumido listado de conceptos bsicos, esta informacin puede
encontrarse en forma ms elaborada en el WikiLibro Fundamentos de programacin.
Definiciones
Se denomina algoritmo a una secuencia de instrucciones que permiten obtener un
resultado en particular. No necesariamente son programas de computadora, una receta de
cocina, o las instrucciones para cambiar un neumtico son ejemplos de algoritmos de la vida
real.
Las computadoras, son maquinas sin inteligencia propia, cuya nica finalidad es
interpretar el cdigo que se les provee.
El lenguaje de mquina es el nico lenguaje que la computadora "entiende" y es capaz
de ejecutar.
Los lenguajes de programacin son el medio de comunicacin entre el programador y
una computadora. El programador escribe en algn lenguaje de programacin y utiliza las
herramientas provistas por ese lenguaje para transformarlo en lenguaje de mquina.
Finalmente, denominamos programa a una secuencia de rdenes a ser ejecutadas por
una computadora. Un programa debe estar escrito en algn lenguaje de programacin, y puede
incluir uno o ms algoritmos.
Tipos de lenguajes
Existe una gran cantidad de lenguajes de programacin, que estn pensados para distintas
finalidades, siguen distintos paradigmas, y de una u otra forma se diferencian de los dems.
Esquemas de programacin
El esquema de programacin llamado Programacin Imperativa, consiste en escribir una
secuencia de instrucciones una detrs de la otra, que se ejecutarn en orden. Algunas de esas
instrucciones pueden hacer que la mquina pase a una instruccin que no sea la siguiente, tal
vez porque se cumpla una condicin que hayamos establecido.
En los ltimos aos ha tomado fuerza otro paradigma de computacin, llamado Programacin
Orientada a Objetos , en el cual se intentan modelar los sistemas creados como extensiones de
la realidad mediante la definicin de "objetos" que modelan entidades de la vida real y que
interactan entre s mediante "mensajes" llamadas mtodos.
El lenguaje C es un lenguaje imperativo, no orientado a objetos.
Alto o bajo nivel
Por otro lado, los lenguajes de programacin se clasifican en niveles. Un lenguaje es de
ms bajo nivel cuanto ms cercano est al cdigo de mquina, y un lenguaje que es de ms alto
nivel cuanto ms lejano est de la mquina y ms cercano al lenguaje humano.
C es un lenguaje de alto nivel aunque tiene muchas caractersticas de lenguaje de bajo nivel
(como el uso que permite hacer de la memoria). Estas caractersticas hacen que C sea un
lenguaje muy potente, ya que permite optimizar al mximo los recursos de la mquina. Por
ende, esto tambin hace que la dificultad y que los errores que se puedan cometer
programando aumenten. As que a C se le considera de nivel medio.
Lenguajes de ms alto nivel que C son aquellos en los que el programador no necesita
encargarse de manipular la memoria, como Java, C#, Python, Ruby, entre otros.
Compilados o interpretados
Otra forma de clasificar a los lenguajes de programacin que es segn la forma en que se
ejecutan sus rdenes. Existen los lenguajes que son interpretados, cuyas rdenes pasan a
travs de un intrprete que se encarga de ejecutarlas (a partir del cdigo fuente) en el mismo
momento en que estn siendo ledas. Algunos de los lenguajes interpretados
son Python, Perlo Tcl, entre muchos otros.
La contraparte de los lenguajes interpretados son los lenguajes compilados (como el mismo C)
que se diferencian en que las rdenes son transformadas a lenguaje de mquina que se
almacena en un archivo ejecutable. Ese archivo puede ejecutarse luego, sin recurrir al
compilador.
Los lenguajes compilados tienen la ventaja de la velocidad y la eficiencia, pero los interpretados
tienen la ventaja de que, generalmente, son muy portables y de ms alto nivel.
Estructura de la memoria
Parte de esta potencia de C viene de que permite acceder con mucha libertad a la memoria de
la mquina. Para entender un poco cmo es posible, debemos entender cmo se guardan los
datos en la memoria.
Imaginemos que la memoria tiene un montn de casillas, una enorme fila de casillas, cada una
de las cuales contiene un dgito binario (bit):
0101001010100001010101001010000100111010110010010101001011010110001101010110
101010110111...
Es exactamente as, pero es ms cmodo recordar que esos bits se encuentran agrupados de
ocho en ocho, formando octetos (bytes):
01010010 10100001 01010100 10100001 00111010 11001001 01010010 11010110 00110101 01101010 10110111 ...
Cada octeto puede contener combinaciones distintas de ceros y unos, es decir,
cualquier nmero entre 0 y 255:
82 161 84 161 58 201 82 214 181 106 183 ...
Tambin podemos representar estos nmeros en base hexadecimal:
0x52 0xA1 0x54 0xA1 0x3A 0xC9 0x52 0xD6 0x35 0x6A 0xB7 ...
O considerarlos caracteres, mediante alguna codificacin:
R T : R 5 j ...
Este es el tipo de dato ms elemental que nos podemos encontrar en C: el caracter. Un caracter
ocupa exactamente un byte (8 bits) de memoria, y puede contener un nmero entre 0 y 255, o
entre -128 y 127, dependiendo si queremos considerarlo como sin signo o con l.
Primer programa en C
En el libro "El Lenguaje de Programacin C", Kernighan y Ritchie introdujeron al lenguaje C
utilizando un sencillo programa que mostraba un saludo por la pantalla. Desde entonces se hizo
tradicin empezar con cualquier lenguaje de programacin con el ejemplo del Hola mundo.
En particular en C se involucran muchas partes y sintaxis del lenguaje, por lo cual es
especialmente til verlo como el primer ejemplo de programacin en C.
Ejemplo: Hola mundo
/* Inclusin de archivos */
#include <stdio.h>

/* Funcin principal */
int main (int argc,char **argv)
{
/* Impresin por pantalla y salida del programa*/
printf("Hola mundo\n");
return 0;
}
Para poder editar y ejecutar este programa ser necesario utilizar algn editor y luego un
compilador, como se explic en la seccin Herramientas necesarias.
Si se tiene el compilador gcc en un entorno UNIX o GNU/Linux, la forma sencilla de compilar y
ejecutar ser:
$ gcc holamundo.c
$ ./a.out
Hola Mundo
$
Es decir que el compilador genera un archivo, en este caso llamado a.out, y la salida generada
por ese archivo es "Hola mundo". A continuacin una explicacin detallada sobre el proceso de
compilacin del programa, y luego un anlisis lnea por lnea del contenido de este ejemplo.

Pre-requisitos para la compilacin de programas
Como ya se mencion, ser necesario tener instalado el compilador y un editor o entorno de
desarrollo que permitan escribir el cdigo a compilar. Para ms informacin ver la
seccinHerramientas necesarias.
El cdigo a compilar debe guardarse con un nombre que represente al programa en cuestin y
la extensin .c. En el caso del ejemplo del Hola mundo, el archivo puede llamarse hola.c.
En las explicaciones a continuacin, se asume que se cuenta con un compilador instalado y se ha
editado un archivo hola.c que se quiere compilar. Si tu sistema operativo no aparece en esta lista
busca en internet, ya que seguro que existe algn compilador para ese sistema.
Compilacin de programas segn la plataforma
Windows
Para compilar un programa C en entornos Windows, debemos seguir una serie de pasos que
varan segn el compilador de C que queramos utilizar. Antes que nada, sera bueno que se
revises la documentacin del compilador elegido para conocer los comandos exactos.
Compilacin del cdigo fuente
Si se utiliza un entorno de desarrollo, ser posible compilar directamente desde el entorno,
mediante un botn o una combinacin de teclas.
Si se ejecuta el compilador desde la lnea de comandos, la lnea ser distinta segn el
compilador utilizado. A continuacin algunos ejemplos de ciertos comandos segn el
compilador:
En Turbo C de Borland es: tcc hola.c
En C++ de Borland: bcc hola.c
En Visual C de Microsoft: cl hola.c
En GNU gcc: gcc hola.c o cc hola.c
El C de Zortech: ztc hola.c
Una vez compilado el cdigo fuente se genera un archivo llamado archivo objeto o programa
objeto que es luego enlazado mediante el enlazador, para generar el archivo ejecutable.
Los compiladores actuales suelen hacer dos funciones de una vez, compilando y enlazando todo
en una sola funcin, aunque es posible pedirles que no lo hagan mediante parmetros
adicionales.
Segn el compilador y la configuracin utilizada, se obtendrn dos o tres archivos:
El archivo fuente
hola.c
El archivo objeto
hola.obj
El archivo ejecutable
hola.exe
Este ltimo es el que nos interesa, puesto a que es el cdigo ejecutable, el programa en s. Al
ejecutarlo se producir la salida deseada en una ventana de consola.
Salida por pantalla
Si ejecutamos en entorno Windows el programa directamente desde el navegador de archivos,
o tambin desde algunos entornos de desarrollo, lo que suceder ser que apenas abierta la
ventana de la consola, se mostrar la cadena esperada y luego de terminada la funcin, la
consola se cerrar sin tener el tiempo suficiente de ver nuestro mensaje en pantalla.
Para poder ver la salida por pantalla ser necesario ejecutar el programa desde la lnea de
comandos, o modificar la configuracin del entorno de desarrollo para que muestre la salida
por pantalla al ejecutar el programa.
Una posible solucin es agregar una funcin adicional a nuestro "hola.c":
/* Inclusin de archivos */
#include <stdio.h>
#include <stdlib.h>

/* Funcin principal */
int main (int argc,char **argv)
{
/* Impresin por pantalla y salida del programa*/
printf("Hola mundo\n");
system ("pause");
return 0;
}
Las dos lneas agregadas permiten que utilicemos la biblioteca stdlib, que incluye la
funcin system y que mediante esta funcin se ejecute el comando pause del sistema, que evita
que el programa siga hasta que se presione una tecla.
As es posible visualizar que la salida de hola.c se complet perfectamente.

Linux
Si bien existen otros compiladores, lo ms usual y ms sencillo para compilar un programa en
GNU/Linux es el compilador gcc, ya que es el que se incluye en todas las distribuciones.
De cualquier forma, es posible realizar la compilacin desde lnea de comandos o desde el
entorno grfico.
Para realizarla desde lnea de comandos, ser necesario contar con una terminal (xterm,
konsole, gnome-terminal, etc). No es necesario contar con permisos de root para crear o
compilar programas. En esa terminal ser necesario escribir
gcc hola.c
Si no existen errores en el cdigo, este comando nos crear un archivo ejecutable, que por
omisin se llama "a.out", y que podemos ejecutar desde la lnea de comandos de la siguiente
forma:
./a.out
Hola mundo
Es una buena idea especificar el nombre que el archivo ejecutable tendr, pasando como
parmetro al compilador la opcin -o, de la siguiente forma:
gcc hola.c -o hola
Con lo cual, el nombre del archivo creado ser hola. Este archivo no tiene extensin ya que es la
forma usual de llamar a los archivos ejecutables en los entornos UNIX y GNU/Linux, sin embargo
funcionara de la misma forma si se llamara hola.exe.
Para ejecutarlo, haremos los mismo que en el caso anterior:
./hola
Hola mundo
Existen otros parmetros que podemos especificar al compilador en la lnea de comandos,
dependiendo del tipo de programa, y en funcin de la complejidad del mismo. Por ejemplo,
podemos agregar las siguientes opciones:
gcc hola.c -o hola -Wall -pedantic
La opcin -Wall nos mostrar todos los avisos que produzca el compilador, no solamente los
errores. Los avisos nos indican dnde y/o porqu podra surgir algn error en nuestro
programa.
La opcin -pedantic nos aporta ms informacin sobre los errores y los avisos mostrados por
GCC.
Diseccionando el "Hola Mundo"
A continuacin veremos cul es la estructura bsica de un programa en C, para poder entender
qu hace cada una de las lneas de nuestro sencillo programa.
Es probable que lo primero que salte a la vista sea la lnea:
printf("Hola mundo\n");
Esta es la lnea que hace aparecer la cadena Hola Mundo en nuestra pantalla. Notamos que en C
la sentencia para imprimir algo por pantalla es printf() y, adems, hay que colocar parntesis
alrededor de lo que queremos imprimir para utilizarla.
Esto se debe a que en C, printf es una funcin, que imprime su argumento (la cadena Hola
Mundo\n) en la pantalla. Se denomina invocar una funcin a la accin de utilizarla para que
realice una accin.
Podemos observar tambin que la cadena a imprimir termina con una extraa combinacin: \n.
La combinacin \n no representa a dos caracteres independientes, sino que representa un nico
carcter no imprimible: el salto de lnea. Sin el salto de lnea, el resultado al ejecutar el
programa sera:
$ ./a.out
Hola Mundo$
Es decir que no hay salto de lnea entre la cadena impresa, y la siguiente entrada de la lnea de
rdenes, que no es lo que esperbamos.
Lo ltimo a notar en la lnea es que termina con un punto y coma. En C, todas las sentencias
terminan con un punto y coma. Al principio puede parecer obvio dnde termina una sentencia,
pero ya veremos ms adelante que no lo es tanto.
Observemos ahora la siguiente sentencia del programa:
return 0;
Luego de esta sentencia, termina el programa. En el caso de la instruccin return dentro de la
funcin main, el resultado es que se finaliza el programa, comunicndole al sistema
operativo que el valor de retorno (un cdigo numrico que el sistema utiliza para saber si el
programa ha funcionado bien o ha dado fallos) es 0, es decir, correcto.
Las dos ltimas sentencias se encuentran encerradas entre llaves. De esta manera, forman
un bloque, es decir, un grupo de sentencias que se ejecutarn siempre de correlativa.
Y qu es esa lnea que precede (en realidad, que da nombre) al bloque?
int main (int argc, char **argv)
Pues es la definicin de una funcin, en este caso llamada main. En C (y en general en todos los
lenguajes de programacin estructurada) todo se hace a base de funciones, como main yprintf.
La funcin main es especial, porque es el la que se invoca cuando se ejecuta el programa. Todos
los programas en C comienzan su ejecucin al principio de la funcin main, y cuando sta acaba,
el programa tambin.
Veamos con ms detalle la definicin de la funcin:
int main (int argc, char **argv)
{
...
}
El nombre de la funcin que viene a continuacin, entre llaves, es main.
Recibe dos argumentos: int argc y char **argv (que representan a la cantidad de
argumentos ingresados al ejecutar el programa y a los valores de estos argumentos
respectivamente).
[1]

La funcin devuelve como resultado un nmero entero, int (que es el 0 de la
instruccin return).
[2]

Finalmente, y un tanto aparte (est separada del resto por una lnea en blanco), tenemos la
lnea:
#include <stdio.h>
Que parece bastante distinta al resto del programa, y que, adems, parece no tener sentido,
puesto que ya hemos definido la funcin main que hace todo el trabajo.
Efectivamente, esa lnea no es parte del programa, aunque sea imprescindible. La lnea es una
instruccin del preprocesador de C, como nos lo indica el smbolo #, y lo que hace es incluir en
ese punto el contenido de otro fichero, antes (de ah el nombre de preprocesador) de que
comience la compilacin. El fichero stdio.h es el que contiene la definicin de la funcinprintf(),
que antes utilizamos pero que no escribimos, ya que forma parte de la biblioteca estndar de C.
Comentarios
Una vez escrito un cdigo, tratar de entenderlo un ao ms tarde solo con leerlo puede ser
frustrante: no hay manera de saber (si el programa es medianamente complicado) qu es cada
variable, o qu hace cada bloque de cdigo. Por esto, en cualquier lenguaje de programacin
son importantes los comentarios.
Un comentario en C es todo lo que se encuentre entre los smbolos /* y */. Hay que tener en
cuenta que los comentarios no se pueden anidar: si dentro de un comentario hay un /*, seguir
siendo el primer */ el que finalice el comentario, no se esperar al segundo.
Hay otro tipo de comentarios en C, procedentes del lenguaje C++, e incorporadas al estndar
de C a partir de C99: //. Todo lo que est despus de estos signos, hasta el final de la lnea, se
considerar un comentario y el compilador no lo tomar en cuenta.
En el ejemplo presentado pueden verse tres lneas con comentarios, que documentan
someramente las distintas funcionalidades del cdigo. En los prximos captulos podrn verse
mejores usos de los comentarios dentro del cdigo.
Tambin podra decirse que es una herramienta bsica basada en compilador

1. Volver arriba En un captulo posterior podr ver un ejemplo del uso de los parmetros que
recibe main.
2. Volver arriba Es importante sealar que el estndar dice que main deber definirse como funcin
que retorna un entero, o de lo contrario el resultado queda indefinido.


Tipos de datos
Historia
En el lenguaje C estandarizado como C89, existan cuatro tipos de datos bsicos que son: los
nmeros enteros, los nmeros reales, los caracteres, y los punteros. A partir del estndar C99
se agregan: los valores lgicos (verdadero o falso) y los nmeros complejos.
Estos tipos de datos son parte del lenguaje, y por ello se los considera primitivos. Ms adelante
veremos que con el uso de estructuras y uniones es posible crear tipos compuestos de datos a
partir de estos tipos primitivos.
En este captulo veremos los enteros, los reales y los caracteres. Ms adelante se vern otros
tipos de datos ms complejos, como son los vectores, las cadenas de caracteres, y los punteros
en general.
Enteros
Los enteros son el tipo de dato ms primitivo en C. Se usan para representar nmeros enteros.
Pero siempre se pueden encontrar otras aplicaciones para los nmeros enteros. En general se
pueden usar para representar cualquier variable discreta.
Los tipos de datos enteros son: short, int, long y long long, cada uno representando un nmero
entero de un tamao o capacidad determinado. Segn el compilador y la plataforma de
hardware, cada uno de estos tipos de dato puede ocupar desde 1 byte hasta 8 bytes en
memoria (para ms detalles busca en la referencia).
Adems, el lenguaje C hace la distincin de si el entero es con signo (signed) o sin signo
(unsigned). En caso de que no se declare si es con signo o sin signo, se toma con signo.
Algunos ejemplos de declaraciones de enteros:
int a;
unsigned int a;
signed long a;
signed long long a = 10000000;
Todos los nmeros son representados en memoria mediante una cadena de bits. En el caso de
los nmeros con signo, el bit ms significativo es el que se usa para representar el signo. La
representacin de los nmeros negativos se realiza mediante el complemento a dos, que es
una tcnica que permite operar con los nmeros negativos de forma lgica.
A modo de ejemplo, la representacin en memoria del nmero -8 en una variable de 2 bytes,
entera, con signo, sera la siguiente:
1111111111111000

Flotantes
Se denomina flotantes a los tipos de datos que representan a los nmeros reales, ya que
utilizan un sistema de representacin basado en la tcnica de coma flotante, que permite
operar con nmeros reales de diversas magnitudes, mediante un nmero decimal
llamado mantisa y un exponente que indica el orden de magnitud.
El tipo de dato flotante en lenguaje C slo tiene dos tamaos: el float y el double, que son 4 bytes
y 8 bytes respectivamente. Se los puede utilizar tanto para representar nmeros decimales,
como para representar nmeros enteros con un orden de magnitud muy grande.
La forma de declarar una variable flotante es escribiendo en una lnea uno de los tipos de datos
flotantes y a continuacin el nombre de la variable y tal vez algn valor que se les quiera dar.
Algunos ejemplos:
float a;
double a = 1e23;
double a = 3.1416;
float a = 4e-9;
double a = -78;
Hay que tener en cuenta que aunque los valores flotantes son ms convenientes para algunas
aplicaciones, hay casos en los que se prefieren los enteros. Esto se debe a que los nmeros
flotantes no necesariamente tienen soporte de hardware, en particular en las
plataformas integradas. Una alternativa que se utiliza en estas situaciones es interpretar los
enteros como decimales de forma que 150 se interprete como 1.5 y 2345 como 23.45.
Para el caso de los flotantes de 4 bytes, se utiliza 1 bit para el signo, 8 bits para el exponente y
23 bits para el valor del nmero. El procedimiento para almacenar un nmero en una variable
flotante es el siguiente:
1. Se convierte a binario la parte entera.
2. Se coloca el signo en el bit ms significativo de la misma manera que en los enteros (1
para el - y 0 para el +).
3. Se mueve la coma (en la representacin binaria de la parte entera) hasta que est a la
derecha del primer uno y ste se descarta (el uno ms significativo). El valor del exponente ser
el nmero de posiciones que se movi la coma. El exponente usa la representacin de un
entero con complemento a dos.
4. Se convierte en binario la parte decimal del nmero. Esto usando el peso de los bits. el
bit decimal ms significativo vale 1/2, el siguiente vale 1/4, el otro 1/8, el otro 1/16 y as hasta
completar lo que falta para los 23bits del valor.
5. Se concatena todo y ese es el valor flotante representado en memoria.
Caracteres
Los caracteres se representan utilizando el tipo char, que tiene slo 1 byte de tamao. Este tipo
se utiliza para representar los 256 caracteres de la tabla de caracteres del sistema. El tipochar es
tambin un tipo entero, ya que puede tomar valores de 0 a 255. Por lo tanto tambin puede
ser signed o unsigned.
En cuanto a la forma de declarar variables de tipo char es la misma forma que con los otros
tipos.
char a;
char a = 's';
unsigned char a = 48;
Como puedes ver, se le puede asignar un nmero a una variable char, ya que se trata de un tipo
entero. En muchas situaciones se utiliza el tipo char para almacenar nmeros pequeos, ya que
ocupa en memoria slamente un byte.
Es importante notar que con la llegada de la codificacin UTF-8, los caracteres de los diversos
idiomas pueden ocupar 1, 2, 3 o 4 bytes, de modo que el tipo char ya no alcanza para la
representacin de todos los caracteres posibles. Por ello, el estndar C99 introduce el
tipo wchar que puede ocupar ms de 1 byte, segn sea necesario para la codificacin utilizada
por el sistema.

Interaccin con el usuario
En este captulo veremos un poco ms sobre como interactuar con el usuario de nuestros
programas desde la consola, utilizando printf() como vimos en el primer ejemplo "Hola mundo",
as como scanf() para la lectura del teclado.
Imprimir por pantalla
Como hemos visto hasta ahora en los ejemplos, hay una funcin que utilizamos para sacar por
pantalla textos arbitrarios o el resultado de alguna operacin: la funcin printf().
Si miramos (en la documentacin) su definicin, no nos aclarar demasiado:
int printf (const char *TEMPLATE, ...)
...claro que por algo tiene una seccin completa de la documentacin para ella sola.
Vemosla poco a poco. Se trata de una funcin de la biblioteca estndar, lo que quiere decir
que para utilizarla tenemos que incluir previamente su definicin. La encontraremos en<stdio.h>.
Lo primero que vemos en la definicin es que es una funcin de tipo int, lo que quiere decir que
devuelve un entero. Ese entero es el nmero de caracteres impresos en la pantalla, o un
nmero negativo en caso de que se produzca algn error.
Lo siguiente a notar es su primer argumento: const char *TEMPLATE. Se trata de una cadena de
caracteres (char *) que no ser modificada por la funcin (const), con lo que puede ser una
constante de cadena o una variable que contenga una cadena, pero siempre debe acabar con el
carcter nulo \0.
Y luego vienen esos extraos puntos suspensivos. Esa elipsis nos indica que como argumentos
adicionales de printf() podemos poner una serie ilimitada de otros argumentos, que se supone
que la funcin sabr qu hacer con ellos. Y eso es justamente lo que hace tan fabulosa y til
a printf().
Como hemos visto, el uso ms simple de printf() es imprimir una cadena de texto simple y
corriente. Como ya vimos:
printf("Hola Mundo\n"); /*imprime la cadena*/
Y tambin hemos visto printf() tambin puede, con un argumento extra y una sintaxis especial,
imprimir un nmero entero que hayamos almacenado en una variable:
char resultado;

resultado=5+2;
printf("Resultado de la suma: %i\n",resultado);
Aqu el punto de insercin es la secuencia %i. printf() siempre trata las secuencias que comiencen
por % como secuencias de control que le dicen que debe imprimir algo que le proporcionamos
en los otros argumentos. As, podemos imprimir varios enteros distintos en los sitios que
queramos de la cadena, insertando varias de estas secuencias %i:
int numero;

numero=3;
printf("El doble de %i es %i y su cuadrado es %i\n",numero,numero*2,numero*numero);
Lectura de datos del teclado
La entrada de datos se puede hacer de muchas maneras y entre ellas estn desde el uso de
dispositivos especiales hasta nuestro simple teclado. La entrada de datos se refiere a cualquier
forma de influencia del usuario sobre los datos que posee el sistema.
Con el fin de mostrar una forma de entrada simple para el aprendizaje vamos a hablar de la
funcin scanf() que se encuentra definida en <stdio.h> y que se usa para capturar diferentes tipos
de datos.
La funcin scanf()
scanf() es una de las funciones ms usadas por los principiantes para hacer entrada de datos en
el lenguaje C. Tiene una sintaxis muy parecida a printf: recibe una cadena con el formato de los
datos y luego se ponen las variables en orden que correspondan a ese tipo de datos. Es decir,
as como en printf se pueden mostrar por pantalla los datos de varias variables en una misma
sentencia, en scanf se pueden capturar varios datos en una sola sentencia.
#include <stdio.h>
int main() {
int a;
printf ("diga un valor para a:");
scanf("%i",&a);
printf ("el valor es: %i\n",a);
return 0;
}
Por ahora no nos interesan las dems sentencias, slo la que contiene scanf. En el cdigo se ve
lo siguiente:
scanf("%i",&a);
Se observa que la funcion printf dej en pantalla una peticin para que el usuario introdujera un
valor. Entonces, scanf recibe como argumento una cadena del formato en que se van a capturar
los datos y la lista de variables que van a recibir valores y que deben coincidir con los del
formato.
En este caso la cadena de formato, "%i", especifica que el usuario ingresar un nmero entero.
Luego se designa a la variable a para contener a ese nmero. El smbolo (&) que precede aa es
para especificar que lo que se est enviando como argumento no es el valor que posee la
variable a sino la direccin de memoria en que se encuentra. En este momento eso no tiene
mucha relevancia, slo hay que recordar que se debe usar el smbolo & dentro del scanf. En el
momento en que hablemos de punteros veremos ms detalles de esto.
Otro ejemplo del uso de scanf:
#include <stdio.h>
int main() {
int a,b;
printf ("introduzca dos valores con el formato \"a,b\" :");
scanf("%i,%i",&a,&b);
printf ("el primer valor : %i\n",a);
printf ("el segundo valor : %i\n",b);
return 0;
}
Aqu hemos introducido una nueva variable en el cdigo. La cadena de
formato, "%i,%i" especifica que el usuario ingresar un nmero, seguido de una coma, y luego
otro nmero. El primer %i ser capturado por la variable a y el segundo por b.

Expresiones
Vamos a tratar ahora de que el ordenador haga un poco de matemticas para nosotros. Por
ejemplo, que realice unas pocas sumas, restas multiplicaciones y divisiones.
#include <stdio.h>

int main(void)
{
int resultado;

resultado=5+2;
printf("Resultado de la suma: %i\n",resultado);
resultado=5-2;
printf("Resultado de la resta: %i\n",resultado);
resultado=5*2;
printf("Resultado de la multiplicacin: %i\n",resultado);
resultado=5/2;
printf("Resultado de la divisin: %i\n",resultado);
return(0);
}
Despus de grabarlo (por ejemplo, con el nombre ejemplo.c), lo compilamos y ejecutamos, con
(respectivamente):
$ gcc ejemplo.c
$ ./a.out
Resultado de la suma: 7
Resultado de la resta: 3
Resultado de la multiplicacin: 10
Resultado de la divisin: 2
$
Fijmonos en la lnea del principio de la funcin main:
int resultado;
Esta lnea lo que hace es reservar un trozo de memoria, del tamao de un int (normalmente 4
bytes), y asignarle el nombre resultado, para poder despus referirnos a l. A partir de este
momento, podemos considerar que en nuestro programa existe una variable, que no tiene
valor definido, pero a la que le podremos dar valor posteriormente.
Las lneas con printf() ya las conocemos, pero hay algo en ellas que no habamos visto antes.
Esos %i y la parte de resultado son nuevas para nosotros.
La funcin printf() no slo sabe imprimir cadenas simples, como "Hola Mundo\n", sino tambin
imprimir variables. Para ello, en el lugar de la cadena donde queremos que aparezca el valor de
la variable, introducimos lo que se llama una cadena de conversin de printf(). Estas cadenas
siempre empiezan por %, siendo %i la cadena para imprimir un entero, como es en nuestro
caso int resultado. Finalmente, printf() debe saber qu valor escribir, por eso le damos otro
argumento (u otros), usando , como separador, que contienen las variables cuyos valores
queremos mostrar.
En el resto del programa hemos visto cmo decirle al ordenador que ejecute una suma, una
resta, una multiplicacin y una divisin entera, con los operadores +, -, * y /. Es de notar que el
resultado de una operacin como estas entre nmeros enteros ser siempre otro entero, como
se puede observar en la divisin, en la que no obtenemos un bonito decimal, sino un resultado
entero. Adems, hemos visto que el resultado de esas operaciones, que llamamos expresiones,
puede ser asignado a una variable:
resultado = 7;
Esa asignacin se hace mediante el operador de asignacin: =. Con l, ya conocemos cinco
operadores.
Pero, como = tambin es un operador, cmo sabe el ordenador qu operador debe ejecutar
primero? Y si es un operador, por qu no da un resultado? No crea una expresin?
Operadores Precedencia
* / Izq. a Der.
+ - Izq. a Der.
= Der. a Izq.
Empezando por las ltimas preguntas, el operador de asignacin s crea una expresin, como
los operadores de suma, resta, multiplicacin y divisin, y esa expresin tiene un resultado, que
es el valor que obtiene el lado izquierdo al realizar la operacin. En cuanto a saber qu se debe
ejecutar primero, el ordenador tiene una lista de precedencia, segn la cual siempre ejecuta
primero las multiplicaciones y divisiones, de izquierda a derecha, a continuacin las sumas y
restas, de izquierda a derecha, y a continuacin las asignaciones, de derecha a izquierda. Para
ms detalles acerca de la precedencia de los operadores ver el anexo de los operadores.
En cuanto a los caracteres de punto y coma, notamos aqu que una expresin tambin puede
ser una sentencia por s misma, sin necesidad de que haya ninguna funcin. De hecho, una
sentencia puede no tener siquiera una expresin. La lnea: ; es una sentencia perfectamente
vlida, la sentencia vaca, que sera til en puntos donde el lenguaje requiera una sentencia pero
no sea necesaria para nuestro programa.

Instrucciones de control
Como ya se ha mencionado, C es un ejemplo de programacin estructurada. En este tipo de
programacin, es necesario contar con ciertas estructuras que permitan controlar el flujo del
programa, es decir, tomar decisiones y repetir acciones.
La estructura condicional if ... else
En la gran mayora de los programas ser necesario tomar decisiones sobre qu acciones
realizar. Esas decisiones pueden depender de los datos que introduzca el usuario, de si se ha
producido algn error o de cualquier otra cosa.
La estructura condicional if ... else es la que nos permite tomar ese tipo de decisiones.
Traducida literalmente del ingls, se la podra llamar la estructura "si...si no", es decir, "si se
cumple la condicin, haz esto, y si no, haz esto otro".
Un ejemplo sencillo sera el siguiente (no se trata de un programa completo, sino tan slo una
porcin de cdigo):
if (edad < 18)
printf("No puedes acceder.\n");
else
printf("Bienvenido.\n");
Este cdigo de ejemplo dice que si el valor de la variable edad es menor que 18 se
imprimir "No puedes acceder.\n", mientras que en caso contrario se
imprimir "Bienvenido.\n".
Como se ve en el ejemplo, la estructura de un condicional es bastante simple:
if (condicin) {
sentencias_si_verdadero;
} else {
sentencias_si_falso;
}
La condicin, encerrada entre parntesis, es una expresin que puede dar como
resultado 0 (interpretado como falso) o cualquier valor distinto de 0 (interpretado
como verdadero). Cuando la condicin sea verdadera, se ejecutarn las sentencias dentro del
primer bloque de cdigo, cuando la condicin sea falsa, se ejecutarn las sentencias del
segundo bloque de cdigo. Las expresiones y valores de tipo verdadero/falso son tambin
llamados valores lgicos o booleanos.
La indentacin o sangra (los espacios al comienzo de las lneas) no es necesaria, pero ayuda a la
claridad del cdigo. La utilizacin de las llaves {...} es obligatoria cuando se quiere utilizar ms
de una instruccin por bloque, y optativa cuando slo se quiere escribir una instruccin. Por
claridad, sin embargo, es recomendable utilizarlas an cuando slo vaya a haber una
instruccin.
El bloque del else es opcional. Si no se lo encuentra, slo se realizar la accin correspondiente
al bloque if.
A continuacin, un ejemplo con una funcin, que devuelve el mayor de dos nmeros:
int mayor(int a, int b)
{
if (b > a) {
return b;
}// No posee especificacin de la parte "else", ya que no es necesaria.
return a; // Finaliza la funcin retornando el valor de "a".
}
Operadores de comparacin
El smbolo > visto en el ltimo ejemplo es un operador, que en este caso compara dos nmeros
enteros y devuelve verdadero si el primero es mayor, falso en caso contrario.
A continuacin un listado de los posibles operadores de comparacin en C y su significado.
Operadores de Comparacin
Operador Significado
< estrictamente menor que
> estrictamente mayor que
<= menor o igual que
>= mayor o igual que
== igual a
!= distinto de

Teniendo en cuenta que en C se toma como falso el valor 0, y como verdadero cualquier otro
valor, una prctica comn es expresar condiciones sin utilizar ningn operador:
float division(int dividendo, int divisor)
{
if (divisor) {
return dividendo / divisor;
} else {
printf ("No se puede dividir por cero\n");
return 0;
}
}
En este caso, la expresin (divisor) es equivalente a (divisor != 0).
Operadores lgicos
Los operadores && ("y"), || ("o") y ! ("no") son operadores lgicos. Permiten operar con
expresiones lgicas para generar expresiones ms complejas.
Por ejemplo: determinar si un ao es bisiesto o no. Los aos son bisiestos si son divisibles por 4,
pero no si son divisibles por 100, a menos que tambin sean divisibles por 400.
if ( (!(a % 4) && ((a % 100))) || !(a % 400) ) {
printf("es un ao bisiesto.\n");
} else {
printf("no es un ao bisiesto.\n");
}
En realidad, teniendo en cuenta la prioridad de los operadores utilizados, podemos simplificar
la expresin anterior del siguiente modo:
if ( !(a % 4) && (a % 100) || !(a % 400) ) {
printf("es un ao bisiesto.\n");
} else {
printf("no es un ao bisiesto.\n");
}
Adems, como a cada rama del if le sigue una nica instruccin, podemos expresar la expresin
anterior del siguiente modo:
if ( !(a % 4) && (a % 100) || !(a % 400) )
printf("es un ao bisiesto.\n");
else
printf("no es un ao bisiesto.\n");

En este caso, se utiliza el operador mdulo (%), que obtiene el resto de la divisin entera de un
nmero por otro. Cuando un nmero es divisible por otro, el resto de su divisin entera ser
cero. Siendo que cero es equivalente a falso, y cualquier valor distinto de cero es equivalente a
verdadero, podemos usar el operador % para verificar si el nmero es mltiplo de 4, de 100 o
de 400.

Evaluacin de cortocircuito
La evaluacin en corto circuito es una caracterstica del lenguaje C que se utiliza para optimizar
la ejecucin de programas. Consiste en que el programa puede verificar si una expresin es
verdadera o falsa antes de haber evaluado toda condicin.
Por ejemplo, si se tiene una condicin como la siguiente:
if ((a > 2) || (b < 4)) {
...
}
Al ejecutarse el programa, se evaluar primero si a > 2. En el caso en que sea verdadero, no
continuar con la siguiente condicin, ya que el resultado ser de cualquier modo verdadero.
De la misma forma, si la condicin fuera:
if ((a > 2) && (b < 4)) {
...
}
En este caso, si no se cumple que a > 2, no se evaluar la siguiente condicin, ya que el
resultado ser falso de todos modos.
Esta caracterstica no tiene demasiada importancia al comenzar a programar, pero facilitar
ciertas operaciones y optimizaciones en programas avanzados.

La estructura condicional switch ... case
La estructura condicional switch ... case se utiliza cuando queremos evitarnos las llamadas
escaleras de decisiones. La estructura if nos puede proporcionar, nicamente, dos resultados,
uno para verdadero y otro para falso. Una estructura switch ... case, por su parte, nos permite
elegir entre muchas opciones. Ejemplo:
#include <stdio.h>
#include <stdlib.h>

int main(void) {
int dia;

printf("que nmero de da de la semana es?");
scanf("%d",&dia);

switch(dia) {
case 1 :
printf("Lun, Lunes");
break;
case 2 :
printf("Mar, Martes");
break;
case 3 :
printf("Mier, Miercoles");
break;
case 4 :
printf("Jue, Jueves");
break;
case 5 :
printf("Vie, Viernes");
break;
case 6 :
printf("Sab, Sabado");
break;
case 7 :
printf("Dom, Domingo");
break;
default :
printf("No existe");
}
return 0;
}
La estructura anterior, de realizarse con sentencias if, necesitara cuatro de ellas, resultando un
enorme bloque muy difcil de leer. En la mayora de los casos, adems, la
sentencia switchproporciona una ganancia en velocidad del cdigo, pues permite al compilador
trabajar en base a que se trata de una decisin mltiple para una nica variable, cosa que con
sentencias ifel compilador no tiene por qu detectar.
Como vemos, para cada valor de la variable se ejecuta un bloque de sentencias distinto, en el
que no necesitamos llaves. Hay un caso especial, default, que se ejecuta si ningn otro
corresponde, y que no es necesario poner. Es, en todo, equivalente al bloque else de una
sentencia if.
Las sentencias break son muy importantes, ya que el comportamiento normal de un
bloque switch es ejecutarlo todo desde la etiqueta case que corresponda hasta el final. Por ello,
si no queremos que se nos ejecute ms de un bloque, pondremos sentencias break al final de
cada bloque excepto el ltimo.
Es decir, las etiquetas case son puntos de entrada de la ejecucin, y no implican que al acabarse
el bloque case la ejecucin salte al final del bloque switch. Las etiquetas case siguientes a la
que hemos utilizado para entrar son, sencillamente, ignoradas.
A la ausencia de sentencias break se le llama, en ocasiones, "dejar caer la cascada switch".
El bucle while
El bucle while sirve para ejecutar cdigo reiteradas veces.
while (/*condicion*/) {
/* Cdigo */
}
La condicin debe de ser una expresin lgica, similar a la de la sentencia if. Primero se evala
la condicin. Si el resultado es verdadero, se ejecuta el bloque de cdigo. Luego se vuelve a
evaluar la condicin, y en caso de dar verdadero se vuelve a ejecutar el bloque. El bucle se corta
cuando la condicin da falso.
Ejemplo: imprimir los nmeros de 0 a 99:
int i = 0;
while (i < 100) {
printf("%d\n", i);
i = i + 1;
}
El bucle for
El bucle for es un bucle muy flexible y a la vez muy potente ya que tiene varias formas
interesantes de implementarlo, su forma ms tradicional es la siguiente:
for (/* inicializacin */; /* condicin */; /* incremento */) {
/* cdigo a ejecutar */
}
Inicializacin: en esta parte se inicia la variable que controla el bucle y es la primera sentencia
que ejecuta el bucle. Slo se ejecuta una vez ya que solo se necesita al principio del bucle.
Expresin condicional: al igual que en el bucle while, esta expresin determina si el bucle
continuar ejecutndose o no.
Incremento: es una sentencia que ejecuta al final de cada iteracin del bucle. Por lo general, se
utiliza para incrementar la variable con que se inicio el ciclo. Luego de ejecutar el incremento, el
bucle revisa nuevamente la condicin, si es verdadera tiene lugar una ejecucin ms del cuerpo
del ciclo, si es falsa se termina el ciclo y as.
Aqu se muestra el mismo ejemplo visto para el bucle while, pero implementado con un bucle for:
int i;
for (i=0; i < 100; i = i + 1) {
printf("%d\n", i);
}
Nota: En C, la sentencia i = i + 1 puede escribirse en forma ms reducida como i++. Esta forma se
utiliza ms comnmente en el bucle for:
int i;
for (i=0; i < 100; i++) {
printf("%d\n", i);
}
El bucle do...while
El bucle do...while es un bucle que, por lo menos, se ejecuta una vez. Do significa literalmente
"hacer", y while significa "mientras"
Su forma es esta:
do {
/* CODIGO */
} while (/* Condicin de ejecucin del bucle */)
Os muestro un ejemplo sencillo de uso:
int aleatorio;
do {
aleatorio = rand();
} while (aleatorio != 25);
La verdad es que este ejemplo puede resultar un poco absurdo, pero es bastante intuitivo. El
cdigo del bucle asigna un valor aleatorio a la variable definida anteriormente, y mientras esa
variable no tenga el valor 25, el bucle sigue ejecutndose.
La sentencia goto
La sentencia goto sirve para indicar al programa que continue ejecutndose desde la lnea de
cdigo indicada. Su sintaxis es ms o menos as:
/* Cdigo */
ETIQUETA:
/* Cdigo */
goto ETIQUETA;
/* Cdigo */
As, cuando se ejecute la sentencia goto, el programa "saltar" y continuar su ejecucin a
partir de la etiqueta marcada.
Como se puede observar se puede usar para crear un bucle, o para ir a una parte del cdigo u
otra si se combina con una sentencia if...else. Pero por lo general puede obtenerse el mismo
efecto utilizando los bucles anteriormente vistos.
Por eso, la sentencia goto es poco aceptada por la comunidad de programadores, pues puede
provocar que se hagan programas un poco "sucios" y confusos. Slo en ocasiones muy
excepcionales ser recomendado el uso del goto al crear iteraciones muy complejas. Sin
embargo, con el pasar de los aos este comando ya ha quedado prcticamente descartado del
lenguaje de los programadores.

Uso de Funciones
Funciones
Como vimos anteriormente C tiene como bloque bsico la funcin main() , tambin hemos visto
la sentencia printf() que es otra funcin, y de igual forma hay muchas ms funciones
predefinidas, pero nosotros mismos tambin podemos definir nuestras propias funciones. De
hecho, es fundamental hacerlo.
Podemos definir una funcin cualquiera de la misma manera en que definimos la
funcin main(). Basta con poner su tipo, su nombre, sus argumentos entre parntesis y luego,
entre llaves, su cdigo:
/* Inclusin de archivos */
#include <stdio.h>

void holamundo(void) /* Funcin donde se ejecuta la lgica del programa */
{
printf("Hola Mundo\n"); /* imprime la cadena */
return; /* sale de la funcin */
}

int main(void) /* Funcin principal del programa */
{
holamundo(); /* llamada a la funcin holamundo */
return 0; /* sale del programa con cdigo 0 (correcto) */
}
Este cdigo es en todo equivalente al "Hola Mundo" original, slo que nos muestra cmo
escribir y cmo utilizar una funcin. Y adems nos muestra un principio de buena programacin:
meter las sentencias que "hacen el trabajo" en otras funciones especficas para sacarlas
de main(), dejando en sta tan slo un guin general de lo que hace el programa, no las rdenes
especficas. De esta manera se facilita la comprensin del programa, y por tanto el futuro
trabajo de modificarlo.
La sentencia return
La sentencia return puede utilizarse dentro de una funcin para terminar su ejecucin.
En el ejemplo anterior, la funcin holamundo fue declarada con valor de retorno de
tipo void (es decir, valor de retorno nulo). En ese caso, la sentencia return no lleva ningn
parmetro adicional, ya que la funcin no debe devolver ningn valor a la funcin que la llama.
En cambio, la funcin main tiene un valor de retorno de tipo int, por lo que return debe ir
seguido de un valor entero (0 en el ejemplo). El valor 0 se utiliza para indicar que el programa
ha llegado a un punto en el que todo se ha desarrollado correctamente y se utiliza cualquier
otro valor para indicar que ha habido algn tipo de error.
La instruccin return no es una funcin, se trata de una sentencia que lo que hace es retornar
como valor de la funcin el valor que se le proporciona como argumento.
Argumentos
Las funciones tambin pueden recibir argumentos o parmetros, para modificar su
comportamiento. Por ejemplo, la definicin de una funcin para sumar dos nmeros sera de la
siguiente manera:
#include <stdio.h>

int sumar(int numero1, int numero2)
{
return numero1 + numero2;
}

int main(void)
{
int suma = sumar(5, 3);
printf("La suma es: %d ", suma);
return 0;
}
En este ejemplo, la funcin sumar recibe dos argumentos de tipo int y su valor de retorno
tambin es de tipo int. Dentro de la funcin main, se llama a la funcin sumar poniendo entre
parntesis los valores deseados para sus argumentos, en orden, separados por una coma. As,
dentro de sumar el nmero 5 ser asignado a la variable numero1 y el nmero 3 a numero2.
Declaracin y definicin
En el ejemplo anterior podemos notar que la funcin sumar figura en el cdigo antes que main.
Qu pasara si las escribiramos en distinto orden?
#include <stdio.h>

int main(void)
{
int suma = sumar(5, 3); /* ERROR, sumar no ha sido declarada an */
printf("La suma es: %d ", suma);
return 0;
}

int sumar(int numero1, int numero2)
{
return numero1 + numero2;
}
En este caso el programa es errneo y no compila, ya que en la lnea donde se llama a la
funcin sumar, el compilador an no conoce ninguna funcin con ese nombre, y cules son sus
argumentos y valor de retorno.
Una posible solucin es declarar el prototipo de la funcin al principio, para informar al
compilador que existe, y luego definir el cuerpo de la misma en cualquier lugar del programa:
#include <stdio.h>

/* Declaracin */
int sumar(int numero1, int numero2);

int main(void)
{
int suma = sumar(5, 3);
printf("La suma es: %d ", suma);
return 0;
}

/* Definicin */
int sumar(int numero1, int numero2)
{
return numero1 + numero2;
}
Paso de Parmetros
Las funciones pueden recibir datos como lo hemos observado, pero existen dos formas de
enviar los datos hacia una funcin por valor ypor referencia, las cuales modifican en diferente
forma el comportamiento de el programa.

Por Valor
El paso por valor enva una copia de los parmetros a la funcin por lo tanto los cambios que se
hagan en ella no son tomados en cuenta dentro de la funcin main(). Ejemplo:
/*
* por_valor.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

void sumar_valor(int numero); /* prototipo de la funcin */

int main(void)
{
int numero = 57; /* definimos numero con valor de 57*/

sumar_valor(numero); /* enviamos numero a la funcin */

printf("Valor de numero dentro de main() es: %d\n", numero);
/* podemos notar que el valor de numero se modifica
* slo dentro de la funcin sumar_valor pero en la principal
* nmero sigue valiendo 57
*/

return 0;
}

void sumar_valor(int numero)
{
numero++; /* le sumamos 1 al numero */

/* el valor de nmero recibido se aumenta en 1
* y se modifica dentro de la funcin sumar_valor()
*/
printf("Valor de numero dentro sumar_valor() es: %d\n", numero);

return;
}
Por Referencia
El paso por referencia se hace utilizando apuntadores. Se enva la direccin de memoria de la
variable, por lo tanto los cambios que haga la funcin si afectan el valor de la variable. Ejemplo:
/*
* por_referencia.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

void sumar_referencia(int *numero); /* prototipo de la funcin */


int main(void)
{
int numero = 57; /* definimos numero con valor de 57*/

sumar_referencia(&numero); /* enviamos numero a la funcin */

printf("\nValor de numero dentro de main() es: %d ", numero);
/* podemos notar que el valor de numero se modifica
* y que ahora dentro de main() tambin se ha modificado
* aunque la funcin no haya retornado ningn valor.
*/

return 0;
}

void sumar_referencia(int *numero)
{
*numero += 1; /* le sumamos 1 al numero */

/* el valor de numero recibido se aumenta en 1
* y se modifica dentro de la funcin
*/
printf("\nValor de numero dentro sumar_referencia() es: %d", *numero);

return;
}
Variables Locales y Globales
Adems de pasar valores a una funcin, tambin se pueden declarar tipos de datos dentro de
las funciones, estos tipos de datos declarados dentro de una funcin solo son accesibles dentro
de esta misma funcin y se les conocen como variables locales, as pues podemos definir los
mismos nombres de variables en diferentes funciones, ya que estas variables solo son
accesibles dentro de esas funciones. Ejemplo:
/*
* locales.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

void funcion1()
{
int dato = 53; /* definimos dato en 53*/
char num1 = 'a'; /* num1 vale a */

/* imprimimos */
printf("Funcion1, dato=%d, num1=%c\n", dato, num1);

return;
}

void funcion2()
{
int dato = 25; /* definimos dato en 25*/
char num2 = 'z'; /* num2 vale z*/

/* imprimimos */
printf("Funcion2, dato=%d, num2=%c\n", dato, num2);

return;
}

int main(void)
{
funcion1(); /* llamamos a funcion1() */

funcion2(); /* llamamos a funcion2() */

return 0;
}
En este caso la variable dato, esta definida dentro de cada una de las funciones y son
totalmente distinta una de otra y no se puede utilizar fuera de esta, as pues num2 no puede
ser utilizada por la funcion1() y num1 tampoco puede ser utilizada por funcion2().
Existen pues variables que se definen fuera de la funcin principal main() y fuera de cualquier
otra funcin creada por nosotros, estas variables se les conoce con el nombre de Variables
Globales ya que se pueden utilizar dentro de main() y dentro de cualquier funcin creada por
nosotros. Ejemplo:
/*
* global.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

int variable_global = 99; /* inicializamos la variable global */

void funcion();

int main(void)
{
/* imprimimos el valor*/
printf("main(), acceso a variable_global %d\n", variable_global);

/* llamamos a la funcin */
funcion();

return 0;
}

void funcion()
{
/* imprimimos el valor*/
printf("funcion(), acceso a variable_global %d\n", variable_global);

return;
}
Funciones Recursivas
La recursividad (recursin) es la propiedad por la cual una funcin se llama a s
misma directa o indirectamente. La recursin indirecta implica utilizar ms de una funcin.
Se puede considerar la recursividad como una alternativa a la iteracin. La recursin permite
especificar soluciones naturales, sencillas, que seran, en caso contrario, difciles de resolver.
Toda funcin recursiva debe contemplar un caso base o condicin de salida, para terminar, o la
recursividad no podr terminar nunca.
Una funcin recursiva podra definirse as:
funcion_recursiva( /* parmetros recibidos por la funcin */ )
{
/* Cdigo */
funcion_recursiva( ); /* llamada a la funcin misma */
/* Cdigo */
}
Uno de los ejemplos ms representativos en la recursividad es el factorial de un numero ( n! ):

la definicin de recursividad del factorial es:

En esta definicin, n = 0, es nuestro caso base, que le da fin a la recursividad.
Entonces nuestro programa que calcula el factorial es:
/*
*factorial.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

long factorial(int n)
{
if (n == 0) /* caso base */
return 1; /* como 0! = 1, se retorna 1*/
else
return n * factorial (n - 1); /* llamada a esta misma funcin */
}

int main(void)
{
/* en este caso se llama a la funcin y se imprime directamente*/
printf("%ld ", factorial(5));

return 0;
}
Tambin existen otros tipos de funciones recursivas como lo es el producto de dos nmeros. El
producto de a b, donde a y b son nmeros enteros positivos seria:
Solucin iterativa:

Solucin recursiva:

As pues es:

Podemos ver que la multiplicacin de dos nmeros a, b se puede transformar en otro problema
ms pequeo multiplicar a por (b-1), el caso base se produce cuando b = 0 y el producto es0.
Ejemplo:
/*
* producto.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

int producto(int a, int b)
{
if (b == 0) /* caso base */
return 0; /* como b = 0, se retorna 0*/
else
return a + producto (a, b - 1); /* llamada a esta misma funcin */
}

int main(void)
{
/* en este caso se llama a la funcin y se imprime directamente*/
printf("%i ", producto( 7, 3));

return 0;
}
Recursividad indirecta o recursin mutua
Esta se produce cuando una funcin llama a otra, que esta a su vez terminar llamando de
nuevo a la primera funcin. El siguiente programa visualiza el alfabeto utilizando recursin
indirecta o mutua:
/*
* elalfabeto.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

void funcionA(char c); /* se declara el prototipo de la funcin para que el llamado */
void funcionB(char c); /* a la misma en la funcin no sea implcita */

int main(void)
{

funcionA('z'); /* llamado a funcionA */

return 0;
}

void funcionA(char c)
{
if (c > 'a') /* caso base mientras c no sea menor que A */
funcionB(c); /* llamado a la funcionB */

printf("%c ", c); /* imprimimos el valor de c */
*la variable es un parametro no utilizado para este proceso
}

void funcionB(char c)
{
funcionA(--c); /* llamado a la funcionA decrementando el valor de 'z' */
}
Recursin versus Iteracin
Tanto la iteracin como la recursin se basan en estructura de control: la iteracin utiliza una
estructura repetitiva y la recursin una estructura de seleccin. La iteracin utiliza
explcitamente una estructura repetitiva mientras que la recursin consigue la repeticin
mediante llamadas repetitivas a funciones.
La iteracin termina si la condicin del bucle no se cumple, mientras que la recursin termina
cuando se reconoce un caso base.
La recursin puede presentar desventajas ante la iteracin ya que se invoca repetidas veces al
mecanismo de llamada de funciones y se necesita un tiempo mayor para realizar cada llamada.
La razn por la cual se puede elegir u optar por usar recursividad es que existen muchos
problemas complejos que poseen naturaleza recursiva y, en consecuencia, son mas fciles de
implementar.
Ejemplo Iterativo
/*
* iterativo.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

long factorial(int numero);

int main(int argc, char** argv)
{
int contador = 0;

/* calcula el factorial de 0 a 10 */
for ( contador = 0; contador <= 10; contador++ )
printf("%d! = %ld\n", contador, factorial( contador ));

return 0;
}

/* funcion factorial iterativa */
long factorial( int numero )
{
long resultado = 1;
int i = 0;

/* declaracion de la funcin factorial iterativa */
for ( i = numero; i >= 1; i-- )
resultado *= i;

return resultado;
}
Ejemplo Recursivo
/*
* recursivo.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

long factorial(int numero);

int main(int argc, char** argv)
{
int contador = 0;

/* calcula el factorial de 0 a 10 */
for ( contador = 0; contador <= 10; contador++ )
printf("%d! = %ld\n", contador, factorial( contador ));

return 0;
}

/* funcin factorial recursiva */
long factorial( int numero )
{
if ( numero <= 0 ) /* caso base */
return 1; /* casos bases: 0! = 1 y 1! = 1 */
else /* llamada recursiva */
return numero * factorial( numero - 1 ); /* llamada a la funcin factorial */
}

Vectores
Los vectores son una forma de almacenar datos que permiten contener una serie de valores del
mismo tipo, cada uno de los valores contenidos tiene una posicin asociada que se usar para
accederlos. Est posicin o ndice ser siempre un nmero entero positivo.
En C la cantidad de elementos que podr contener un vector es fijo, y en principio se define
cuando se declara el vector. Los vectores se pueden declarar de la siguiente forma:
tipo_elemento nombre[largo];
Esto declara la variable nombre como un vector de tipo_elementos que podr
contener largo cantidad de elementos, y cada uno de estos elemento podr contener un valor
de tipotipo_elemento.
Por ejemplo:
double valores[128];
En este ejemplo declaramos un vector de 128 elementos del tipo double, los ndices de los
elementos iran entre 0 (para el primer elemento y 127 para el ltimo).
De la misma forma que con las otras declaraciones de variables que hemos visto se le puede
asignar un valor iniciar a los elementos.
O tambin se pueden declarar:
tipo_elemento nombre[largo]={valor_0, valor_1, valor_2};
En caso estamos asignadole valores a los primeros 3 elementos del vector nombre. Notar
que largo debe ser mayor o igual a la cantidad de valores que le estamos asignando al vector,
en el caso de ser la misma cantidad no aporta informacin, por lo que el lenguaje nos permite
escribir:
tipo_elemento nombre[]={valor_0, valor_1, valor_2};
Que declarar nombre como el vector de largo 3.
Para acceder a un elemento accederemos a travs de su posicin. Es decir:
tipo_elemento elemento;
...
elemento = nombre[2];
Asumiendo que tenemos el vector anterior definido estaramos
guardando valor_2 en elemento.
Veamos algunos ejemplos:
/*
* Ejemplo : El producto escalar de dos vectores
*/
#include <stdio.h>

double producto_escalar(double v1[], double v2[], int d);

int main()
{
const int largo = 3;
double vector_1[] = {5,1,0};
double vector_2[] = {-1,5,3};

double resultado = producto_escalar(vector_1, vector_2, largo);

// imprime el resultado
printf("(%f, %f, %f) . (%f, %f, %f) = %f\n",
vector_1[0], vector_1[1], vector_1[2],
vector_2[0], vector_2[1], vector_2[2],
resultado);
return 0;
}

/* producto escalar entre dos vectores */
double producto_escalar(double v1[], double v2[], int d)
{
double resultado = 0;
int i;
for (i=0; i < d; i++) {
resultado += v1[i] * v2[i];
}
return resultado;
}
En el ejemplo anterior usamos los vectores de C para representar vectores matemticos y
calcular el producto escalar entre ellos. Una peculiaridad que se puede notar es que al recibir
un arreglo en una funcin no se especifica el largo, volveremos a esto en un captulo posterior.
Otra funcin clsica es la bsqueda de un mximo o mnimo, que podemos escribirla de la
siguiente manera:
int buscar_maximo(double valores[], int num_valores)
{
int maximo_pos = 0;
for (int i = 1; i < num_valores; i++) {
if (valores[i] > valores[maximo_pos]) {
maximo_pos = i;
}
}
return maximo_pos;
}
Otro ejemplo sencillo, calcular el promedio de los valores.
double promedio(double valores[], int largo)
{
double suma=0;
for (int i=0;i<largo;i++) {
suma+=valores[i];
}
return suma/largo;
}
Cuando una funcin recibe un vector por parmetro y cambia su contenido y el cambio es
permanente (se ve an fuera de la funcin). Esto puede parecer extrao despus del nfasis
que pusimos en resaltar que todos los parmetros de una funcin se reciben por valor, pero se
aclarar en el siguiente capitulo.
Mientras tanto usemos esto para definir una funcin que le aplique otra funcin que recibe por
parmetro a cada elemento del vector, guardando el resultado en el mismo vector y una
llamada de ejemplo a esta.
void cuadrados(double vector[], int largo)
{
for (int i=0;i<largo;i++) {
vector[i]=cuadrado(vector[i]);
}
}
...
double cuadrado(double valor) {
return valor*valor;
}
...
cuadrados(elementos,num_elem);
...
De la misma forma que venimos usando vectores de tipos bsicos, podemos tener vectores de
vectores, estos se declaran de la siguiente forma:
int matriz[3][7];
int tabla[3][4]={ { 1, 2, 3, 4},
{ 5, 6, 7, 8}, /* los espacios y saltos de lneas no son tomados en cuenta */
{ 9,10,11,12} };
double v[2][2][2];
...
printf("tabla[0][1]: %i\n", tabla[0][3]); // Imprime 4
printf("tabla[2][0]: %i\n", tabla[2][0]); // Imprime 9
...
En este ejemplo tabla es un vector de longitud 3, cuyos elementos son vectores de longitud 4
de elementos de tipo int.
En resumen, suponiendo que v[n] es un vector de cualquier tipo de dato con n cantidad de
posiciones, al vector v se le aplican las siguientes reglas:
1. La primera posicin siempre ser v[0]
2. La ltima posicin es v[n-1]
3. En versiones previas a C99 n es una constante definida antes de la declaracin de v[n]

Cadenas de caracteres

Las cadenas de caracteres (tambin llamadas cadenas o strings) son un tipo particular de vectores, son de
hecho vectores de char, con la particularidad que tienen una marca de fin (el caracter '\0'), adems el
lenguaje nos permite escribirlas como texto dentro de comillas dobles. Veamos unos ejemplos de su
declaracin:
char cadena_hola[]="Hola";
char otro_hola[]={'H','o','l','a','\0'}; // Igual al anterior
char vector[]={'H','o','l','a'}; /* Un vector de 4 elementos,
con los elementos 'H','o','l' y 'a' */
char espacio_cadena[1024]="Una cadena en C";
char cadena_vacia[]="";
Cmo vimos anteriormente al declarar un vector se define la cantidad de elementos que puede contener, en
el caso de las cadenas se debe tener en cuenta el espacio adicional necesario para el \0. Viendo el ejemplo,
tanto cadena_hola y otro_hola tienen un largo 5 y cadena_vacia tiene un largo de 1.
Tambin vimos anteriormente que al usar vectores debemos tener en cuenta su largo, y as es que el largo o
cantidad de elemento lo necesitamos en todas las funciones que definimos usando vectores y lo recibimos
como un parmetro ms en estas, en el caso de las cadenas al tener una marca de fin podemos prescindir del
largo y procesar una cadenas hasta llegar a la marca de fin.

Por ejemplo, la siguiente funcin calcula el largo de una cadena:
/* devuelve la cantidad de caracteres en cadena sin contar el '\0' */
int largo_cadena(char cadena[])
{
int largo=0
while (cadena[largo]!='\0') largo++;
return largo;
}
Se debe tener en cuenta que el largo de una cadena y el largo del vector con la que se representa son
distintos, tanto por como largo_cadena() cuenta el largo de la cadena, como porespacio_cadena del ejemplo
anterior.
Algo bastante usual es necesitar unir dos cadenas, veamos un ejemplo:
bool unir_cadenas(char destino[], char origen[], int largo)
{
int largo_origen = largo_cadena(origen);
int largo_destino = largo_cadena(destino);
if ( largo_origen+largo_destino+1 > largo ) {
return false;
}
for (int i=0; i<largo_origen;i++) {
destino[largo_destino+i] = origen[i];
}
destino[largo_destino+largo_origen]='\0';
return true;
}
...
if ( unir_cadenas(espacio_cadena," que puede crecer hasta 1023 caracteres",1024) ) {
...
Estos dos ejemplos son versiones simplificadas de funciones provistas por la biblioteca estndar de C a travs
del encabezado string.h. Nuestro largo_cadena() es similar al strlen() de la biblioteca estndar,
y unir_cadenas() se asemeja al strncat(). Si bien ver estas versiones nos sirven para entender las cadenas en C,
en general ser preferible usar las funciones provistas por la biblioteca estndar, ya que podemos estar
seguros que van a estar programadas de la mejor manera posible.
Entre las funcione que provee la biblioteca estndar de C, las ms importantes son:
largo = strlen(cadena) // Para obtener el largo de una cadena
strcpy(destino, origen) // Copia el contenido de origen en destino
// destino debe ser lo suficientemente grande
strcat(destino, origen) // Agrega el contenido de origen al final de destino
// destino debe ser lo suficientemente grander
resultado = strcmp(cadena1, cadena2) // Compara dos cadenas
// devuelve un valor menor, igual o mayor que 0 segn si cadena1 es menor,
// igual o mayor que cadena2, respectivamente.
posicion = strchr(cadena, caracter) // Devuelve la posicin en memoria de la primer
// aparicin de caracter dentro de cadena
posicion = strstr(cadena,subcadena) // Devuelve la posicin en memoria de la primer
// aparicin de subcadena dentro de cadena

Veamos algunos ejemplos usando <string.h>:
#include <stdio.h>
#include <string.h>
...
char color[] = "rojo";
char grosor[] = "grueso";
...
char descripcion[1024];

strcpy(descripcion, "Lapiz color ");
strncat(descripcion, color, 1024);
strncat(descripcion, " de trazo ", 1024);
strncat(descripcion, grosor, 1024);
// descripcion contiene "Lapiz color rojo de trazo grueso"
...

void intercambiar(char vector[], int pos1, int pos2);
void invierte_cadena(char cadena[])
{
int largo = strlen(cadena);
for (int i=0; i < (largo/2); i++) {
intercambiar(cadena, i, (largo-1)-i);
}
}
void intercambiar(char vector[], int pos1, int pos2)
{
char aux=vector[pos1];
vector[pos1]=vector[pos2];
vector[pos2]=aux;
}

Manejo de archivos
As como hemos revisado la salida y entrada por pantalla y teclado respectivamente, veremos ahora la
entrada y/o salida de datos utilizando ficheros, lo cual ser imprescindible para un gran nmero de
aplicaciones que deseemos desarrollar.

Ficheros
El estndar de C contiene varias funciones para la edicin de ficheros, estas estn definidas en la
cabecera stdio.h y por lo general empiezan con la letra f, haciendo referencia a file. Adicionalmente se agrega
un tipo FILE, el cual se usar como apuntador a la informacin del fichero. La secuencia que usaremos para
realizar operaciones ser la siguiente:
Crear un apuntador del tipo FILE *
Abrir el archivo utilizando la funcin fopen y asignndole el resultado de la llamada a nuestro
apuntador.
Hacer las diversas operaciones (lectura, escritura, etc).
Cerrar el archivo utilizando la funcin fclose.
fopen
Esta funcin sirve para abrir y crear ficheros en disco.
El prototipo correspondiente de fopen es:
FILE * fopen (const char *filename, const char *opentype);
Los parmetros de entrada de fopen son:
filename: una cadena que contiene un nombre de fichero vlido. opentype: especifica el tipo de fichero que
se abrir o se crear.

Una lista de parmetros opentype para la funcin fopen son:
"r" : abrir un archivo para lectura, el fichero debe existir.
"w" : abrir un archivo para escritura, se crea si no existe o se sobreescribe si existe.
"a" : abrir un archivo para escritura al final del contenido, si no existe se crea.
"rt" : abrir un archivo para lectura y escritura, el fichero debe existir.
"wt" : crear un archivo para lectura y escritura, se crea si no existe o se sobreescribe si existe.
"r+b rb+" : Abre un archivo en modo binario para actualizacin (lectura y escritura).
"rb" : Abre un archivo en modo binario para lectura.

Adicionalmente hay tipos utilizando "b" (binary) los cuales no sern mostrados por ahora y que solo se usan
en los sistemas operativos que no pertenecen a la familia de unix.
fclose
Esta funcin sirve para poder cerrar un fichero que se ha abierto.
El prototipo correspondiente de fclose es:
int fclose (FILE *stream);
Un valor de retorno cero indica que el fichero ha sido correctamente cerrado, si ha habido algn error, el
valor de retorno es la constante EOF.
Un ejemplo pequeo para abrir y cerrar el archivo llamado fichero.in en modo lectura:
#include <stdio.h>

int main(int argc, char** argv)
{
FILE *fp;
fp = fopen ( "fichero.in", "r" );
fclose ( fp );

return 0;
}
Como vemos, en el ejemplo se utiliz el opentype "r", que es para la lectura.
Otra cosa importante es que el lenguaje C no tiene dentro de si una estructura para el manejo de
excepciones o de errores, por eso es necesario comprobar que el archivo fue abierto con xito "if (fp ==
NULL)". Si fopen pudo abrir el archivo con xito devuelve la referencia al archivo (FILE *), de lo contrario
devuelve NULL y en este caso se debera revisar la direccion del archivo o los permisos del mismo. En estos
ejemplos solo vamos a dar una salida con un retorno de 1 que sirve para sealar que el programa termino por
un error.
feof
Esta funcin sirve para determinar si el cursor dentro del archivo encontr el final (end of file). Existe otra
forma de verificar el final del archivo que es comparar el caracter que trae fgetcdel archivo con el
macro EOF declarado dentro de stdio.h, pero este mtodo no ofrece la misma seguridad (en especial al tratar
con los archivos "binarios"). La funcin feof siempre devolver cero (Falso) si no es encontrado EOF en el
archivo, de lo contrario regresar un valor distinto de cero (Verdadero).
El prototipo correspondiente de feof es:
int feof(FILE *fichero);
rewind
Literalmente significa "rebobinar", sita el cursor de lectura/escritura al principio del archivo.
El prototipo correspondiente de rewind es:
void rewind(FILE *fichero);
Lectura
Un archivo generalmente debe verse como un string (una cadena de caracteres) que esta guardado en el
disco duro. Para trabajar con los archivos existen diferentes formas y diferentes funciones. Las funciones que
podramos usar para leer un archivo son:
char fgetc(FILE *archivo)
char *fgets(char *buffer, int tamano, FILE *archivo)
size_t fread(void *puntero, size_t tamano, size_t cantidad, FILE *archivo);
int fscanf(FILE *fichero, const char *formato, argumento, ...);
Las primeras dos de estas funciones son muy parecidas entre si. Pero la tercera, por el numero y el tipo de
parmetros, nos podemos dar cuenta de que es muy diferente, por eso la trataremos aparte junto
al fwrite que es su contraparte para escritura.
fgetc
Esta funcin lee un caracter a la vez del archivo que esta siendo sealado con el puntero *archivo. En caso de
que la lectura sea exitosa devuelve el caracter ledo y en caso de que no lo sea o de encontrar el final del
archivo devuelve EOF.
El prototipo correspondiente de fgetc es:
char fgetc(FILE *archivo);
Esta funcin se usa generalmente para recorrer archivos de texto. A manera de ejemplo vamos a suponer que
tenemos un archivo de texto llamado "prueba.txt" en el mismo directorio en que se encuentra el fuente de
nuestro programa. Un pequeo programa que lea ese archivo ser:
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *archivo;
char caracter;

archivo = fopen("prueba.txt","r");

if (archivo == NULL){

printf("\nError de apertura del archivo. \n\n");
}else{


printf("\nEl contenido del archivo de prueba es \n\n");

while (feof(archivo) == 0)
{
caracter = fgetc(archivo);
printf("%c",caracter);
}
}
fclose(archivo);
return 0;
}
fgets
Esta funcin est diseada para leer cadenas de caracteres. Leer hasta n-1 caracteres o hasta que lea un
cambio de lnea '\n' o un final de archivo EOF. En este ltimo caso, el carcter de cambio de lnea '\n' tambin
es ledo.
El prototipo correspondiente de fgets es:
char *fgets(char *buffer, int tamao, FILE *archivo);
El primer parmetro buffer lo hemos llamado as porque es un puntero a un espacio de memoria del tipo char
(podramos usar un arreglo de char). El segundo parmetro es tamao que es el limite en cantidad de
caracteres a leer para la funcion fgets. Y por ultimo el puntero del archivo por supuesto que es la forma en
que fgets sabra a que archivo debe leer.
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *archivo;

char caracteres[100];

archivo = fopen("prueba.txt","r");

if (archivo == NULL)
exit(1);

printf("\nEl contenido del archivo de prueba es \n\n");
while (feof(archivo) == 0)
{
fgets(caracteres,100,archivo);
printf("%s",caracteres);
}
system("PAUSE");

fclose(archivo);
return 0;
}
Este es el mismo ejemplo de antes con la diferencia de que este hace uso de fgets en lugar de fgetc. La
funcin fgets se comporta de la siguiente manera, leer del archivo apuntado por archivo los caracteres que
encuentre y a ponerlos en buffer hasta que lea un caracter menos que la cantidad de caracteres especificada
en tamao o hasta que encuentre el final de una linea (\n) o hasta que encuentre el final del archivo (EOF). En
este ejemplo no vamos a profundizar mas que para decir que caracteres es un buffer, los pormenores seran
explicados en la seccin de manejo dinmico de memoria.
El beneficio de esta funcin es que se puede obtener una linea completa a la vez. Y resulta muy til para
algunos fines como la construccin de un parser de algn tipo de archivo de texto.
fread
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
Esta funcin lee un bloque de una "stream" de datos. Efecta la lectura de un arreglo de elementos "count",
cada uno de los cuales tiene un tamao definido por "size". Luego los guarda en el bloque de memoria
especificado por "ptr". El indicador de posicin de la cadena de caracteres avanza hasta leer la totalidad de
bytes. Si esto es exitoso la cantidad de bytes ledos es (size*count).

PARAMETROS:
ptr : Puntero a un bloque de memoria con un tamao mnimo de (size*count) bytes.
size : Tamao en bytes de cada elemento (de los que voy a leer).
count : Nmero de elementos, los cuales tienen un tamao "size".
stream: Puntero a objetos FILE, que especifica la cadena de entrada.
fscanf
La funcin fscanf funciona igual que scanf en cuanto a parmetros, pero la entrada se toma de un fichero en
lugar del teclado.
El prototipo correspondiente de fscanf es:
int fscanf(FILE *fichero, const char *formato, argumento, ...);
Podemos ver un ejemplo de su uso, abrimos el documento "fichero.txt" en modo lectura y leyendo dentro de
el.
#include <stdio.h>


int main ( int argc, char **argv )
{
FILE *fp;

char buffer[100];

fp = fopen ( "fichero.txt", "r" );

fscanf(fp, "%s" ,buffer);
printf("%s",buffer);

fclose ( fp );

return 0;
}
Escritura
As como podemos leer datos desde un fichero, tambin se pueden crear y escribir ficheros con la
informacin que deseamos almacenar, Para trabajar con los archivos existen diferentes formas y diferentes
funciones. Las funciones que podramos usar para escribir dentro de un archivo son:
int fputc(int caracter, FILE *archivo)
int fputs(const char *buffer, FILE *archivo)
size_t fwrite(void *puntero, size_t tamano, size_t cantidad, FILE *archivo);
int fprintf(FILE *archivo, const char *formato, argumento, ...);
fputc
Esta funcin escribe un carcter a la vez del archivo que esta siendo sealado con el puntero *archivo. El
valor de retorno es el carcter escrito, si la operacin fue completada con xito, en caso contrario ser EOF.
El prototipo correspondiente de fputc es:
int fputc(int carcter, FILE *archivo);
Mostramos un ejemplo del uso de fputc en un "fichero.txt", se escribira dentro del fichero hasta que
presionemos la tecla enter.
#include <stdio.h>

int main ( int argc, char **argv )
{
FILE *fp;

char caracter;

fp = fopen ( "fichero.txt", "r+" );

printf("\nIntrouce un texto al fichero: ");

while((caracter = getchar()) != '\n')
{
printf("%c", fputc(caracter, fp));
}

fclose ( fp );

return 0;
}
fputs
La funcin fputs escribe una cadena en un fichero. No se aade el carcter de retorno de lnea ni el carcter
nulo final. El valor de retorno es un nmero no negativo o EOF en caso de error. Los parmetros de entrada
son la cadena a escribir y un puntero a la estructura FILE del fichero donde se realizar la escritura.
El prototipo correspondiente de fputs es:
int fputs(const char *buffer, FILE *archivo)
para ver su funcionamiento mostramos el siguiente ejemplo:
#include <stdio.h>

int main ( int argc, char **argv )
{
FILE *fp;

char cadena[] = "Mostrando el uso de fputs en un fichero.\n";

fp = fopen ( "fichero.txt", "r+" );

fputs( cadena, fp );

fclose ( fp );

return 0;
}
fwrite
Esta funcin est pensada para trabajar con registros de longitud constante y forma pareja con fread. Es
capaz de escribir hacia un fichero uno o varios registros de la misma longitud almacenados a partir de una
direccin de memoria determinada. El valor de retorno es el nmero de registros escritos, no el nmero de
bytes. Los parmetros son: un puntero a la zona de memoria de donde se obtendrn los datos a escribir, el
tamao de cada registro, el nmero de registros a escribir y un puntero a la estructura FILE del fichero al que
se har la escritura.
El prototipo correspondiente de fwrite es:
size_t fwrite(void *puntero, size_t tamano, size_t cantidad, FILE *archivo);
Un ejemplo concreto del uso de fwrite con su contraparte fread y usando funciones es:

fprintf
La funcin fprintf funciona igual que printf en cuanto a parmetros, pero la salida se dirige a un archivo en
lugar de a la pantalla.
El prototipo correspondiente de fprintf es:
int fprintf(FILE *archivo, const char *formato, argumento, ...);
Podemos ver un ejemplo de su uso, abrimos el documento "fichero.txt" en modo lectura/escritura y
escribimos dentro de el.
#include <stdio.h>

int main ( int argc, char **argv )
{
FILE *fp;

char buffer[100] = "Esto es un texto dentro del fichero.";

fp = fopen ( "fichero.txt", "r+" );

fprintf(fp, buffer);
fprintf(fp, "%s", "\nEsto es otro texto dentro del fichero.");

fclose ( fp );

return 0;
}

Estructuras y Uniones

En la creacion de soluciones para algunos problemas surge la necesidad de agrupar datos de diferente tipo o
de manejar datos que serian muy dificil de describir en los tipos de datos primitivos, esta es la situacion en la
que debemos aprovecharnos de las caracteristicas que hacen al lenguaje C especial, o sea el uso de
estructuras, uniones y punteros.
Estructuras
Una estructura contiene varios datos. La forma de definir una estructura es haciendo uso de la palabra
clave struct. Aqui hay ejemplo de la declaracion de una estructura:
struct mystruct
{
int int_member;
double double_member;
char string_member[25];
} variable;
"variable" es una instancia de "mystruct" y no es necesario ponerla aqu. Se podria omitir de la declaracion de
"mystruct" y ms tarde declararla usando:
struct mystruct variable;
Tambin es una prctica muy comn asignarle un alias o sinnimo al nombre de la estructura, para evitar el
tener que poner "struct mystruct" cada vez. C nos permite la posibilidad de hacer esto usando la palabra
clave typedef, lo que crea un alias a un tipo:
typedef struct
{
...
} Mystruct;
La estructura misma no tiene nombre (por la ausencia de nombre en la primera linea), pero tiene de alias
"Mystruct". Entonces se puede usar as:
Mystruct variable;
Note que es una convencion, y una buena costumbre usar mayscula en la primera letra de un sinnimo de
tipo. De todos modos lo importante es darle algn identificador para poder hacer referencia a la estructura:
podriamos tener una estructura de datos recursiva de algn tipo.
Ejemplo de una estructura :
/*
* estructura.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C (fundamentos)"
* bajo licencia FDL, adaptado del Dominio Pblico
*
* Nombre Miembro Tipo
* Titulo char[30]
* Artista char[25]
* Precio float
* Total Canciones int
*/

#include <stdio.h>
#include <string.h>

/* definimos una estructura para cds */
struct cd
{
char titulo[30];
char artista[25];
float precio;
int canciones;
} Cd1 = { /* inicializamos la estructura Cd1 creaa con sus valores
* usando las definiciones iniciales*/
"Canciones Bebe", /* titulo */
"Pinocho", /* artista */
12.50, /* precio */
16 /* total canciones */
};

int main(void)
{
struct cd Cd2; /* definimos una nueva estructura llamado cd2 */

/* asignamos valores a los tipos de datos del cd2 */
strcpy(Cd2.titulo, "New Age");

/* la forma de insertar valores a un
* tipo char en una estructura es usando strcpy
* de la libreria string.h
*/
strcpy(Cd2.artista, "Old Man");
Cd2.precio = 15.00;
Cd2.canciones = 12;

/* la forma de acceder a los valores de una estructura */
/* es usando el "." despues de la definicion del dato*/
printf("\n Cd 1");
printf("\n Titulo: %s ", Cd1.titulo);
printf("\n Artista: %s ", Cd1.artista);
printf("\n Total Canciones: %d ", Cd1.canciones);
printf("\n Precio Cd: %f ", Cd1.precio);

printf("\n");
printf("\n Cd 2");
printf("\n Titulo: %s ", Cd2.titulo);
printf("\n Artista: %s ", Cd2.artista);
printf("\n Total Canciones: %d ", Cd2.canciones);
printf("\n Precio Cd: %.2f ", Cd2.precio); /* el .2 que esta entre %f
* sirve para mostrar unicamente
* 2 decimales despues del punto*/

return 0;
}
Estructuras Anidadas
Una estructura puede estar dentro de otra estructura a esto se le conoce como anidamiento o estructuras
anidadas. Ya que se trabajan con datos en estructuras si definimos un tipo de dato en una estructura y
necesitamos definir ese dato dentro de otra estructura solamente se llama el dato de la estructura anterior.
Definamos una estructura en nuestro programa:
struct empleado /* creamos una estructura llamado empleado*/
{
char nombre_empleado[25];
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
double salario;
}; /* las estructuras necesitan punto y coma (;) al final */
Y luego necesitamos una nueva estructura en nuestro programa:
struct cliente /* creamos una estructura llamada cliente */
{
char nombre_cliente[25];
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
double saldo;
}; /* las estructuras necesitan punto y coma (;) al final */
Podemos ver que tenemos datos muy similares en nuestras estructuras, asi que podemos crear una sola
estructura llamada infopersona con estos datos idnticos:
struct infopersona /* creamos la estructura que contiene datos parecidos */
{
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
}; /* las estructuras necesitan punto y coma (;) al final */
Y crear las nuevas estructuras anteriores, anidando la estructura necesaria:
struct empleado /* se crea nuevamente la estructura */
{
char nombre_empleado[25];
/* creamos direcc_empleado con "struct" del tipo "estructura infopersona" */
struct infopersona direcc_empleado;
double salario;
}; /* las estructuras necesitan punto y coma (;) al final */

<source lang=c>
struct cliente /* se crea nuevamente la estructura */
{
char nombre_cliente[25];
/* creamos direcc_cliente con "struct" del tipo "estructura infopersona" */
struct infopersona direcc_cliente;
double saldo;
}; /* las estructuras necesitan punto y coma (;) al final */
Y ac el ejemplo completo con estructuras anidadas:
/*
* estructura2.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C (fundamentos)"
* bajo licencia FDL, adaptado del Dominio Pblico
*
* Nombre Miembro Tipo
*
* Titulo char[30]
* Artista char[25]
* Precio float
* Total Canciones int
*/

#include <stdio.h>
#include <string.h>

/* creamos nuestra estructura con datos similares */
struct infopersona
{
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
}; /* las estructuras necesitan punto y coma (;) al final */

/* creamos nuestra estructura empleado */
struct empleado
{
char nombre_empleado[25];
/* agregamos la estructura infopersona
* con nombre direcc_empleado
*/
struct infopersona direcc_empleado;
double salario;
}; /* las estructuras necesitan punto y coma (;) al final */

/* creamos nuestra estructura cliente */
struct cliente
{
char nombre_cliente[25];
/* agregamos la estructura infopersona
* con nombre direcc_cliente
*/
struct infopersona direcc_cliente;
double saldo;
}; /* las estructuras necesitan punto y coma (;) al final */

int main(void)
{
/* creamos un nuevo cliente */
struct cliente MiCliente;

/*inicializamos un par de datos de Micliente */
strcpy(MiCliente.nombre_cliente,"Jose Antonio");
strcpy(MiCliente.direcc_cliente.direccion, "Altos del Cielo");
/* notese que se agrega direcc_cliente haciendo referencia
* a la estructura infopersona por el dato direccion
*/

/* imprimimos los datos */
printf("\n Cliente: ");
printf("\n Nombre: %s", MiCliente.nombre_cliente);
/* notese la forma de hacer referencia al dato */
printf("\n Direccion: %s", MiCliente.direcc_cliente.direccion);

/* creamos un nuevo empleado */
struct empleado MiEmpleado;

/*inicializamos un par de datos de MiEmplado */
strcpy(MiEmpleado.nombre_empleado,"Miguel Angel");
strcpy(MiEmpleado.direcc_empleado.ciudad,"Madrid");
/* para hacer referencia a ciudad de la estructura infopersona
* utilizamos direcc_empleado que es una estructura anidada
*/

/* imprimimos los datos */
printf("\n");
printf("\n Empleado: ");
printf("\n Nombre: %s", MiEmpleado.nombre_empleado);
/* notese la forma de hacer referencia al dato */
printf("\n Ciudad: %s", MiEmpleado.direcc_empleado.ciudad);

return 0;
}
printf("No es cierto")
Uniones
La definicion de "union" es similar a la de "estructura", La diferencia entre las dos es que en una estructura,
los miembros ocupan diferentes areas de la memoria, pero en una union, los miembros ocupan la misma area
de memoria. Entonces como ejemplo:
union {
int i;
double d;
} u;
El programador puede acceder a travs de "u.i" o de "u.d", pero no de ambos al mismo tiempo. Como "u.i" y
"u.d" ocupan la misma rea de memoria, modificar uno modifica el valor del otro, algunas veces de maneras
impredecibles.
El tamao de una union es el de su miembro de mayor tamao.
Ejemplo de una unin:
/*
* uniones.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C (fundamentos)"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>
#include <string.h>

/*Creamos una union*/
union frases
{
char mensajes[50];
char ayudas[50];
char lineas[50];
} palabra;

/*Creamos una estructura*/
struct comparte
{
char mensajes[50];
char ayudas[50];
char lineas[50];
}Sistema;

/*Ntese que la estructura y la union tienen los mismos tipos de datos*/

int main(int argc, char** argv)
{
/*Inicializamos*/
strcpy(palabra.mensajes, "Primer Mensaje");

/*Inicializamos*/
strcpy(palabra.ayudas, "Una Ayuda");

printf("\nFrases en Union: ");

/*Imprimimos mensajes de union*/
printf("\n1- %s", palabra.mensajes);

/*Imprimimos ayudas de union*/
printf("\n2- %s", palabra.ayudas);

/*Inicializamos*/
strcpy(Sistema.mensajes, "Primer Mensaje");

/*Inicializamos*/
strcpy(Sistema.ayudas, "Una Ayuda");

/* Podemos notar que aunque inicializamos los valores
* al imprimir se tiene el mismo valor para cada miembro
* de la estructura, esto se debe a que las uniones usan el
* mismo espacio de memoria para todos los elementos
* de la union, siendo del tamao de su miembro de
* mayor tamao, en este caso 50 bytes.
* Entonces los tres miembros creados dentro de la
* union comparten esos 50 bytes.
* Entonces el ultimo valor agregado a la union es
* el que se tiene.
*/

printf("\n\nFrases en Struct: ");

/*Imprimimos mensajes de struct*/
printf("\n1- %s", Sistema.mensajes);

/*Imprimimos ayudas de union*/
printf("\n2- %s", Sistema.ayudas);

/* En la estructura comparte, se reservan 150 bytes
* de memoria para los tres miembros, en este caso
* cada uno es independiente en memoria, asi pues se
* puede inicializar cada uno o usar como un campo
* independiente.
*/

return 0;
}
Enumeraciones
Una enumeracion (enum) es un tipo definido con constante de tipo entero. En la declaracion de un tipo enum
creamos una lista de tipo de datos que se asocian con las constantes enteras 0, 1, 2, 3, 4, 5...
su forma de definirlas es la siguiente:
enum
{
enumerador1, enumerador2, enumeradorn
};

enum Nombre
{
enumerador1, enumerador2, enumeradorn
};
En este caso al ser declaradas enumerador1 toma el valor entero de 0, enumerador2 el valor de 1 y asi
sucesivamente para cada una de las expresiones siguientes.
Al declarar la enum se puede asociar a los tipos de datos a valores constantes en vez de la asociacion que por
defecto se realiza (0, 1, 2, ), se utiliza entonces este formato:
enum Nombre
{
enumerador1 = valor_constante1,
enumerador2 = valor_constante2,
...
enumeradorn = valor_constanten,
};
Un ejemplo de una enum:
enum Boolean
{
FALSE,
TRUE
};
Se definen dos constantes para las constantes true y false con valores iguales a 0 para False y 1 para True.
Ejemplo:
/*
* Enum.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C (fundamentos)"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

enum Boolean
{
FALSE, TRUE
};
/* Se define un enum para emular las constantes
* True y False con valores de 0 y 1.
* Notese que las enum no necesitan ; al final
* de cada tipo de dato.
*/

/* Definimos una funcion del tipo enum llamada numero*/
enum Boolean numero(char c);

int main(int argc, char** argv)
{
char caracter;
int Numeros = 0;

printf("\nIntroduce un texto. Para terminar: Enter. \n\t");

/* Tenemos un while que mientras no se presione Enter
* seguira leyendo un tipo de dato caracter
*/
while((caracter = getchar()) != '\n')
{
if (numero(caracter))
{
Numeros++;
}
}
printf("\nTotal de Numeros leidos: %d", Numeros);

return 0;
}

enum Boolean numero(char c)
{
switch(c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return TRUE;
/* Mientras el caracter valga de 0 a 9 retornara TRUE (1) */
default:
return FALSE;
/* Por default retornara FALSE (0) */
}
}
En la siguiente enum se declaran las variables inicializando la primera y las demas con los siguientes valores
enteros:
/*
* Enum2.c
*
* Julio Csar Brizuela <brizuelaalvarado@gmail.com> 2009
*
* para el wikilibro "Programacin en C (fundamentos)"
* bajo licencia FDL, adaptado del Dominio Pblico
*/

#include <stdio.h>

enum DiasSemanas
{
Domingo = 2,
Lunes,
Marte,
Miercoles,
Jueves,
Viernes,
Sabado
};
/* Podemos inicializar nuestra primer constante Domingo
* en 2, asi pues las demas los siguientes valores enteros.
*/

int main(int argc, char** argv)
{

enum DiasSemanas dia;

for (dia = Domingo; dia <= Sabado; dia++)
{
printf("%d ", dia); /* Salida: 2 3 4 5 6 7 8 */
}

return 0;
}
A los enumeradores se pueden asignar valores o expresiones constantes durante la declaracion:
enum Hexaedro
{
VERTICE = 8,
LADOS = 12,
CARAS = 6
};


Punteros

Concepto
Un puntero es una variable que contiene la direccin de memoria de un dato o de otra variable que contiene
al dato. Quiere esto decir, que el puntero apunta al espacio fsico donde est el dato o la variable. Un puntero
puede apuntar a un objeto de cualquier tipo, como por ejemplo, a una estructura o una funcin. Los punteros
se pueden utilizar para referencia y manipular estructuras de datos, para referenciar bloques de memoria
asignados dinamicamente y para proveer el paso de argumentos por referencias en las llamadas a funciones.
Muchas de las funciones estandares de C, trabajan con punteros, como es el caso del scanf o strcpy. Estas
reciben o devuelve un valor que es un puntero. Por Ej. A scanf se le pasa la direccin de memoria del dato a
leer (esto es un puntero)...
char a;
scanf ("%c",&a);
Declarando punteros
Ya se dijo que un puntero es una variable que guarda la direccin de memoria de otra variable, haciendo
logica a esto, decimos que un puntero se declara igual que cualquier otra variable, pero anteponiendo
un * (asterisco) antes del nombre de la variable.
Su sintaxis seria:
tipo *NombrePuntero;
Donde tipo es el tipo de dato al que referenciar este puntero, es decir, que si se necesita guardar la
direccin de memoria de un dato int, se necesita un puntero de tipo int.
Explicacin
Veamos el siguiente codigo:
#include <stdio.h>

int main()
{
int a=0; //Declaracin de variable entera de tipo entero
int *puntero; //Declaracin de variable puntero de tipo entero
puntero = &a; //Asignacin de la direccin memoria de a

printf("El valor de a es: %d. \nEl valor de *puntero es: %d. \n",a,*puntero);
printf("La direccion de memoria de *puntero es: %p",puntero);

return 0;
}

Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta forma lo usamos aqu, tal
vez te acordaras que decamos que las cadenas de caracteres (%s) no usaban este operador, esto es por
que en una cadena de caracteres es un arreglo de caracteres, por lo que el primer carcter es la direccin
de inicio de la cadena.
El operador *, nos permite acceder al valor de la direccion del puntero, en este caso nos permite acceder
al valor que continiene a. De esta forma "a" y "*puntero" muestran el mismo dato, pero esto no quiere
decir que sea lo mismo, uno es un entero el otro un puntero.
La impresin con %p, es para poder imprimir la direccin de memoria en valor hexadecimal (0x...),
tambin podemos imprimir: ...%p",&a) y funciona de la misma forma, y es lgico que tanto a, como
puntero tienen la misma direccin de memoria.
Diferentes direcciones?
Tal vez notaste que en cada ejecucin la direccin de memoria cambia, esto es por que es el sistema
operativo es quien esta encargado de administrar la memoria y es este quien dice que espacios podra
tomar el programa.
Esto quiere decir que uno no puede asignarle una direccin de memoria a un puntero directamente, es
decir yo no puedo hacer lo siguiente.
int *puntero=0xbfc5b1c8;
Esto no puedo ni debo hacerlo ya que yo no se que esta haciendo esta direccin de memoria, si el sistema
la tiene o no disponible, etc... Pero si puedo hacer esto:
int *puntero=NULL;
NULL, es el espacio en memoria con direccin 0, esto quiere decir que existe, lo que significa que le
asignamos una direccion valida al puntero, pero el valor que tiene NULL no se nos permite modificarlo, ya
que pertenece al sistema.
Operadores
Ya anteriormente te poniamos algunos ejemplos de como asignar la direccin de memoria a un puntero y
de como acceder al valor de este.
Operador de Direccin (&): Este nos permite acceder a la direccion de memoria de una variable.
Operador de Indireccion (*): Ademas de que nos permite declarar un tipo de dato puntero, tambin nos
permite ver el VALOR que esta en la direccin asignada.
Incrementos (++) y Decrementos (--): Te daras cuenta que puedes usar un puntero como si de un array
se tratase, es por esto que permite estos operadores.
De lo anterior podemos decir que:
int a; Es Igual int *puntero=&a; printf("%d",a); Es Igual printf("%d",*puntero);
Operaciones Aritmticas
Un puntero nos permite sumar o restar nmeros enteros, pero su funcionamiento ahora es de posiciones,
es decir nos permitir movernos a la siguiente direccin de memoria.
A un puntero no se le puede realizar multiplicaciones, divisiones, sumas o restas con otro puntero o con
un valor de tipo coma flotante (float, double...). Esto es por que un puntero no es un valor es una
direccin.
En un puntero se pueden realizar varias operaciones de tipo enteras, pero en dependencia de como se
usen sus resultados pueden ser muy diferentes, a continuacin les muestro algunas de estas
operaciones:

//Definamos estas variables:
int x[100],b,*pa,*pb;
//...
x[50]=10; //Le asignamos el valor de 10, al array #50
pa=&x[50]; //Le asignamos al puntero pa, la direccion de memoria que tiene x[50]

//Ahora mostramos algunas posibles operaciones:

b = *pa+1; //Esto es como decir el valor que tiene el array de x[50] sumarle 1.
//Esto es igual a: b=x[50]+1; => Su valor seria igual a 11.

b = *(pa+1); //Esto primero pasa a la siguiente direccion de memoria y luego lo referencia
//El resultado es: b = x[51];

pb = &x[10]; //al puntero pb se le asigna la direccion de x[10]

*pb = 0; //Al valor que tiene el puntero se le asigna 0
//Esto es igual que decir: x[10] = 0

*pb += 2; //El valor del puntero se incrementa en dos unidades, es decir x[10] = 2

(*pb)--; //El valor del puntero se decrementa en una unidad.

x[0] = *pb--; //A x[0] se le pasa el valor de x[10] y el puntero pb, pasa a apuntar a x[9]
//recorda, que -- es post-incremento, primero asignara y luego restara.
Punteros Constantes
Es posible que hayas pensado como declarar un puntero como una constante, tal vez pensaste en
un #define, o en un atributo const. Bueno es posible usar el atributo const, pero para un puntero hay
que hacerlo de otra forma.
FORMA ERRADA:
int a=10,b=20;
const int *p = &a; //objeto constante y puntero variable
*p = 15; // ERROR: el valor apuntado por p es constante.
p=&b; //Correcto: p pasa a apuntar a un nuevo objeto.
Pero de esta forma no es muy til declararlo, pues el que hicimos constante fue el valor al que apunte p,
es decir, mejor hubisemos hecho que el puntero fuese una constante.
FORMA CORRECTA:
int a=10,b=20;
int * const p = &a; //objeto variable y puntero constante
*p = 15; // Correcto: El valor apuntado es variable.
p=&b; //ERROR: p es constante.
Punteros Genericos
Un puntero a cualquier tipo de dato puede convertirse a un puntero del tipo void *. Por esto un puntero
a void *, recibe el nombre de puntero generico.
En C, se permite la conversin implcita de punteros, pero en C++ esto no es posible, asi que por
compatibilidad y buena practica recomendamos usar la conversion explicita (cast).
Supongamos:
int *puntero;
funcion (*puntero);
....
void funcion (void *p)

int *q;
q=(int *)p; //En C se podria hacer q = p;
Es decir que un puntero a void se puede usar sin importar el tipo de dato, recuerden que uno no puede
trabajar con punteros que referencia a un tipo de dato diferente, como lo es un puntero a char, con un
puntero a int.

Punteros y Matrices
Anteriormente decamos que una matriz es una secuencia de espacios en memoria, que nos permitan
alojar datos en cada uno y un puntero es una variable que guarda la direccin de memoria, tambin
decamos como recorre las direcciones de memoria con los operadores ++ y --.
Aqu veremos como puede usarse un puntero como si de una matriz se tratase, luego de que veas que es
tcnicamente lo mismo, te preguntaras por que usar punteros, pero estos son muy necesarios y nicos
que nos permiten realizar cosas que con un array normal, no se puede, como asignarle memoria dinmica,
etc...
#include <stdio.h>

int main()
{

int array[10]={0,2,3,5,5,6,7,8,9,0}; //Declarar e inicializar un array.
int *puntero = &array[0]; //Le damos la direccin de inicio del array
int i; //variable contadora...

for (i=0;i<10;i++)
printf("%d\n",*(puntero+i)); //imprimimos los valores del puntero.

return 0;
}

Habrs notado que he usado *(puntero+i), as como explica la seccin de operaciones aritmticas, pero
tambin podemos acceder de otras maneras como lo son:
array[i] => Accede como un array normal
(array+i) => Tambin accede como un array normal.
puntero[i] => Accedemos al valor de puntero sub i
(puntero+i) => Accedemos al valor de puntero + 1
Punteros a cadenas de caracteres
Ya hemos visto el uso que se le puede dar a un puntero como si de un array se tratase, entonces usando
esta misma logica podemos hacer un array de caracteres usando punteros.
char *nombre="Gustavo A. Chavarria";//Es como un array de 20 caracteres
printf("%s",nombre);
Sin embargo al tratarse de una constante de caracteres no podemos modificarla luego de definir sus
valores. Como por ejemplo no podemos remplazar un carcter, o leer un nuevo valor.
gets(nombre); //ERROR en ejecucin
Para poder modificar el valor de este puntero, este tendra que apuntar a una direccin que no sea una
constante, como un array.
char nombre[]="Gustavo A. Chavarria"; //declaramos un array de caracteres
char *puntero=nombre;//Asignamos al puntero el comienzo del array
printf("%s \nIngrese otro nombre: ",puntero);//Escribimos en pantalla nombre...
gets(puntero); //leemos otro nombre
printf("%s",puntero); //escribimos el nuevo nombre...
Esta vez pudiste notar que si se pudo remplazar el valor del nombre, pero aun la cantidad de caracteres
esta limitada por el array original, mas adelante veremos como solucionar esto con memoria dinmica.
Matrices de Punteros
Es muy probable que ya te hayas dicho: Si un puntero es una variable, Puedo tener un array de punteros?
La respuesta seria NO Exactamente.
Como ya habiamos explicado antes, un puntero trabaja de la misma forma que un array, tanto que
podemos decir que un puntero es un array, entonces si definimos un array de un array, nos dara como
resultados un array bidimensional.
En la practica es mucho mas comn utilizar un array de punteros que un array bidimensional.
Hay que recordar que siguen siendo punteros, es decir solo apuntan a una direccin de memoria, por
ende hay que asignarles la direccin de memoria a cada uno de los elementos del puntero. Sin embargo
podemos asignar en un solo ciclo todas las filas.
Ejemplo:
#include <stdio.h>

int main()
{

int *puntero[5]; //array de puntero
int a[5][5]; //Array bidimensional.
int i;

for (i=0;i<5;i++)
puntero[i]=a[i]; //Asignamos las filas al puntero.

//Pueden imprimir tambien en un ciclo
//Tambien pueden acceder mediante un ciclo anidado a la variables del puntero[i][j]

}
Punteros a Punteros
Es una variable que contiene la direccin de memoria de un puntero, el cual a su vez contiene la direccin
de memoria de un tipo de dato. Recuerden que un puntero sigue siendo un espacio en memoria, pero en
vez de almacenar un valor almacena una direccin.
Si decimos que:
int a=0; //Supongamos que es una variable cuya direccion es 0x1601
int *puntero1=&a; //El puntero tiene guardada la direccion de a,
//pero este tiene como direccion 0x1890
int **puntero2=&puntero1; //**puntero 2 guarda la direccion 0x1890
Ahora se entiende mejor. Al uso de punteros se le llama variables con niveles de indireccion, ya que no
apuntan directamente a un valor, sino que apuntan a alguien que lo tiene. Basndonos en esto podemos
decir que *puntero1 es un puntero con un nivel de indireccion y *puntero2 es un puntero con dos niveles
de indireccion.
En general estos tipos de datos son usados con matrices multidimensionales, es por esto que decid no
dejar ejemplos, pues su uso es bastante fcil de implementar.
Matrices de punteros a cadenas de caracteres
No hablaremos sobre este tema, debido a que es prcticamente una matriz de caracteres que se usa
mediante punteros, y esto es tcnicamente lo mismo que hemos estado viendo anteriormente.
Tambien podemos usar punteros a punteros y guardar multiples cadenas.
Ejemplos
Tenga en cuenta el siguiente bloque de cdigo que declara 2 punteros
/*1*/ struct MyStruct {
/*2*/ int m_aNumber;
/*3*/ float num2;
/*4*/ };
/*5*/
/*6*/ int * pJ2;
/*7*/ struct MyStruct * pAnItem;
Las primeras 4 lneas definen la estructura. La linea 6 declara una variable que apuntar a un entero, y la
lnea 7 declara una variable que apunta a algo de la estructura MyStruct. Entonces declarar un puntero es
algo que apunta a algo de algn tipo, ms que contener el tipo. El asterisco (*) se coloca antes del
nombre de la variable.
En las siguientes lneas de cdigo, var1 es un puntero a un entero largo (long) mientras var2 es un entero
largo (long) y no un puntero a un entero largo. En la segunda lnea se declarap3 como un puntero a un
puntero de un entero.
long * var1, var2;
int ** p3;
Los punteros se usan habitualmente como parmetros de funciones. El siguiente cdigo muestra como
declarar una funcin que usa un puntero como argumento. Teniendo en cuenta que C pasa todos los
argumentos por valor, para poder modificar un valor desde el cdigo de la funcin, se debe usar un
puntero al valor a modificar. Tambin se usan punteros a estructuras como argumentos de una funcin
an cuando la estructura no sea modificada dentro de la funcin. Esto es realizado para evitar copiar
todo el contenido de la estructura dentro de la pila.
int MyFunction( struct MyStruct *pStruct );
Asignando valores a punteros
Continuamos con el proceso de asignar valores a los punteros, para esto utilizamos el operador & o 'la
direccin de'.
int myInt;
int *pPointer;
struct MyStruct dvorak;
struct MyStruct *pKeyboard;

pPointer = &myInt;
pKeyboard = &dvorak;
Aqu, pPointer apuntara a myInt y pKeyboard apuntara a dvorak.
Los punteros tambin pueden ser asignados a referencias de memorias dinamicas creadas comnmente
por las funciones malloc() y calloc().
#include <stdlib.h>
...
struct MyStruct *pKeyboard;
...
pKeyboard = malloc(sizeof(struct MyStruct));
...
La funcin malloc retorna un puntero de memoria asignada de manera dinmica (o NULL si falla). El
tamao de esta memoria es definido de modo que pueda contener la estructura MyStruct
El siguiente cdigo es un ejemplo mostrando un puntero siendo asignado a una referencia y se retorna el
valor del puntero en la funcin.
static struct MyStruct val1, val2, val3, val4;
...
struct MyStruct *ASillyFunction( int b )
{
struct MyStruct *myReturn;

if (b == 1) myReturn = &val1;
else if (b==2) myReturn = &val2;
else if (b==3) myReturn = &val3;
else myReturn = &val4;

return myReturn;
}
...
struct MyStruct *strPointer;
int *c, *d;
int j;
...
c = &j; /* puntero asignado usando el operador & */
d = c; /* asignando un puntero a otro */
strPointer = ASillyFunction( 3 ); /* puntero retornado de la funcion */
Cuando se retorna un puntero de una funcion, se tiene que tener cuidado de que el valor apuntado no
sea de una referencia de una variable local a la funcion, porque estos valores desaparecen despues de
salir de la funcion y el puntero estaria mal referenciado, causando errores en tiempo de ejecucion en el
programa. La memoria creada dinamicamente dentro de la funcion puede devolverse como puntero, el
valor de retorno aunque es creado en una variable local la direccion como tal se devuelve por valor
dejando esta informacion valida.






GNU Free Documentation License

Version 1.2, November 2002
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in
the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without
modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and
publisher a way to get credit for their work, while not being considered responsible for modifications made
by others.
This License is a kind of "copyleft", which means that derivative works of the document must themselves be
free in the same sense. It complements the GNU General Public License, which is a copyleft license designed
for free software.
We have designed this License in order to use it for manuals for free software, because free software needs
free documentation: a free program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals; it can be used for any textual work,
regardless of subject matter or whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that contains a notice placed by the
copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-
wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The
"Document", below, refers to any such manual or work. Any member of the public is a licensee, and is
addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring
permission under copyright law.
A "Modified Version" of the Document means any work containing the Document or a portion of it, either
copied verbatim, or with modifications and/or translated into another language.
A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively
with the relationship of the publishers or authors of the Document to the Document's overall subject (or to
related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the
Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The
relationship could be a matter of historical connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding them.
The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of
Invariant Sections, in the notice that says that the Document is released under this License. If a section does
not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document
may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are
none.
The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover
Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at
most 5 words, and a Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose
specification is available to the general public, that is suitable for revising the document straightforwardly
with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some
widely available drawing editor, and that is suitable for input to text formatters or for automatic translation
to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent
modification by readers is not Transparent. An image format is not Transparent if used for any substantial
amount of text. A copy that is not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input
format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include
PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally
available, and the machine-generated HTML, PostScript or PDF produced by some word processors for
output purposes only.
The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to
hold, legibly, the material this License requires to appear in the title page. For works in formats which do not
have any title page as such, "Title Page" means the text near the most prominent appearance of the work's
title, preceding the beginning of the body of the text.
A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or
contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or
"History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License applies to
the Document. These Warranty Disclaimers are considered to be included by reference in this License, but
only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is
void and has no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either commercially or noncommercially,
provided that this License, the copyright notices, and the license notice saying this License applies to the
Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this
License. You may not use technical measures to obstruct or control the reading or further copying of the
copies you make or distribute. However, you may accept compensation in exchange for copies. If you
distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have printed covers) of the Document,
numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover,
and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the
publisher of these copies. The front cover must present the full title with all words of the title equally
prominent and visible. You may add other material on the covers in addition. Copying with changes limited to
the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as
verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as
many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either
include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque
copy a computer-network location from which the general network-using public has access to download
using public-standard network protocols a complete Transparent copy of the Document, free of added
material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution
of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an Opaque copy (directly or through your
agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing
any large number of copies, to give them a chance to provide you with an updated version of the Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3
above, provided that you release the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution and modification of the Modified Version
to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those
of previous versions (which should, if there were any, be listed in the History section of the Document). You
may use the same title as a previous version if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the
modifications in the Modified Version, together with at least five of the principal authors of the Document
(all of its principal authors, if it has fewer than five), unless they release you from this requirement.
C. State on the Title page the name of the publisher of the Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice giving the public permission to use the
Modified Version under the terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the
Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title,
year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section
Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document
as given on its Title Page, then add an item describing the Modified Version as stated in the previous
sentence.
J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the
Document, and likewise the network locations given in the Document for previous versions it was based on.
These may be placed in the "History" section. You may omit a network location for a work that was published
at least four years before the Document itself, or if the original publisher of the version it refers to gives
permission.
K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and
preserve in the section all the substance and tone of each of the contributor acknowledgements and/or
dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section
numbers or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant
Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections
and contain no material copied from the Document, you may at your option designate some or all of these
sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's
license notice. These titles must be distinct from any other section titles.
You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your
Modified Version by various parties--for example, statements of peer review or that the text has been
approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-
Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover
Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the
Document already includes a cover text for the same cover, previously added by you or by arrangement
made by the same entity you are acting on behalf of, you may not add another; but you may replace the old
one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for
publicity for or to assert or imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this License, under the terms defined
in section 4 above for modified versions, provided that you include in the combination all of the Invariant
Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined
work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may
be replaced with a single copy. If there are multiple Invariant Sections with the same name but different
contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of
the original author or publisher of that section if known, or else a unique number. Make the same adjustment
to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History" in the various original documents,
forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any
sections Entitled "Dedications". You must delete all sections Entitled "Endorsements."
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents released under this License, and
replace the individual copies of this License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for verbatim copying of each of the
documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License,
provided you insert a copy of this License into the extracted document, and follow this License in all other
respects regarding verbatim copying of that document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate and independent documents or works,
in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from
the compilation is not used to limit the legal rights of the compilation's users beyond what the individual
works permit. When the Document is included in an aggregate, this License does not apply to the other
works in the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the
Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers
that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in
electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may distribute translations of the Document under
the terms of section 4. Replacing Invariant Sections with translations requires special permission from their
copyright holders, but you may include translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a translation of this License, and all the license
notices in the Document, and any Warranty Disclaimers, provided that you also include the original English
version of this License and the original versions of those notices and disclaimers. In case of a disagreement
between the translation and the original version of this License or a notice or disclaimer, the original version
will prevail.
If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement
(section 4) to Preserve its Title (section 1) will typically require changing the actual title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under
this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However, parties who have received copies, or rights,
from you under this License will not have their licenses terminated so long as such parties remain in full
compliance.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License
from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a
particular numbered version of this License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or of any later version that has been
published (not as a draft) by the Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not as a draft) by the Free Software
Foundation.

Você também pode gostar