You are on page 1of 133

Introduccin al

Lenguaje de Programacin C

Prof. Jess Lrez

Escuela de Ingeniera Informtica Guayana


Mayo 2013

Introduccin al
Lenguaje de Programacin C

"Si t tienes una manzana y yo tengo una manzana e


intercambiamos las manzanas, entonces tanto t como yo seguiremos
teniendo una manzana. Pero si t tienes una idea y yo tengo una
idea e intercambiamos ideas, entonces ambos tendremos dos ideas.
George Bernard Shaw (1856 - 1950)
Dramaturgo y periodista irlands.

Mayo 2013

Introduccin al
Lenguaje de Programacin C

Contenido
A modo de Presentacin .......................................................................................... 3
Historia y caractersticas del lenguaje C ................................................................ 4
Pasos para la creacin de una aplicacin en lenguaje C ................................. 7
Entorno de Programacin Integrado .................................................................... 12
Estructura de un programa en C ........................................................................... 14
Identificadores .......................................................................................................... 16
Palabras reservadas (C89) ...................................................................................... 17
Variables, alcance y tiempo de vida .................................................................... 21
Tipos de variables ..................................................................................................... 24
Declaracin de variables ........................................................................................ 25
Constantes................................................................................................................. 34
Operadores y expresiones ...................................................................................... 37
Instrucciones (sentencias ejecutables) ................................................................. 49
Funciones y parmetros .......................................................................................... 62
Arreglos, Estructuras, Uniones y Enumeraciones .................................................. 72
Apuntadores ............................................................................................................. 81
La biblioteca estndar ............................................................................................ 97
Entrada y Salida ...................................................................................................... 100
Archivos .................................................................................................................... 102
Memoria Dinmica................................................................................................. 107
Alias, referencias pendientes y basura ............................................................... 109
Funciones con un nmero de parmetros variables ........................................ 109
Pase de parmetros a la funcin main............................................................... 113
El preprocesador .................................................................................................... 114
Llamadas a otros lenguajes de programacin ................................................. 117
Caso de estudio: implementar un comando del sistema ................................ 119
Algoritmos y aplicaciones ..................................................................................... 120
Bibliografa recomendada .................................................................................... 125
ANEXOS .................................................................................................................... 126

Mayo 2013

Introduccin al
Lenguaje de Programacin C

A modo de Presentacin
La presente gua nace como una necesidad de tener una herramienta concisa
para la enseanza del lenguaje de programacin C, en la Universidad Catlica
Andrs Bello Guayana. Est orientada como un instrumento de aprendizaje del
lenguaje y/o de consulta para los estudiantes de la carrera de Ingeniera en
Informtica, con la finalidad de apoyar el uso el lenguaje tanto en cursos bsicos
como el de Algoritmos y Programacin y cursos avanzados tales como Sistemas
Operativos y Sistemas Distribuidos. Sin embargo la misma puede ser utilizada por
cualquier lector interesado en el aprendizaje o uso del lenguaje,
Se asume que el lector tiene nociones bsicas en algoritmos y programacin, es
por esta razn que se que desde un principio se muestran ejemplos de programas
completos para que el lector se inicie lo ms pronto posible en el lenguaje. Sin
embargo los nuevos programadores, con nociones bsica en ingles, podrn leer y
asimilar los concepto del lenguajes.
El contenido trata desde los usos ms elementales hasta los ms avanzados del
lenguaje. Mientras se abarca cada uno de los temas se muestran ejemplos de
programas completos y funcionales que ejemplifican los conceptos expuestos, la
idea es que el lector utilice estos ejemplos en el entorno de programacin de su
preferencia, los compile y ejecute, observando y analizando tanto el cdigo
como los resultados, para posteriormente modificarlos y experimentar. Estos
ejemplos intentan mostrar principios bsicos de la programacin tales como la
simplicidad, la claridad y la generalidad, con la finalidad que el lector pueda
desarrollar un buen estilo de programacin, ya que un programa bien escrito es
ms sencillo de entender y modificar; y tal vez lo ms importante que tiene una
mayor probabilidad de ser correcto.

Mayo 2013

Introduccin al
Lenguaje de Programacin C

Historia y caractersticas del lenguaje C


Este lenguaje fue diseado originalmente para el Sistema Operativo UNIX en la
DEC pdp-11, en implantado en ella por Dennis Ritchie en los Laboratorios Bell,
aunque el Lenguaje C siempre ha estado estrechamente relacionado con UNIX
no est ligado a un Hardware o Sistema de Operacin en particular. A pesar que
es un lenguaje utilizado ampliamente para la programacin de sistemas debido a
su uso en el desarrollo de Sistemas de Operacin, es un lenguaje de
programacin de propsito general, es decir no est especializado en ninguna
rea de aplicacin en particular es decir se puede utilizar para propsitos
mltiples.
El lenguaje C es caracterizado por ser muy conciso y poseer estructuras de control
y datos de alto nivel. Muchas de las caractersticas de C provienen del lenguaje
BCPL, inventado por Martin Richards, llegando a l de forma indirecta a travs del
Lenguaje B, escrito por Ken Thompson en 1970 para el primer sistema UNIX en una
DEC pdp-7.
Durante aos el estndar de C fue la versin proporcionada por la versin V de
UNIX. El cual aparece descrito en el libro The C. Programming Language de
Brian Kernigham y Dennis Ritchie. En 1989 se define el primer estndar por ANSI,
que tambin fue adoptado por la ISO, siendo habitual que se le refiera como
estndar ANSI/ISO y se le conozca habitualmente como C89. Para 1995 aparece
la primera enmienda, que, entre otras cosas incorpora varias funciones de
bibliotecas nuevas. Siendo C89 y la enmienda 1 la base para C++. Para 1999
aparece una nueva versin de C (ANSI/ISO C99) donde se hace nfasis en la
incorporacin de bibliotecas numricas y arreglos de tamao variable.
Al lenguaje C se le denomina como un lenguaje de nivel intermedio, es no
significa que sea menos potente, ms difcil de utilizar o menos evolucionados que
otros lenguajes de alto nivel, sino ms bien su significado es que combina

Mayo 2013

Introduccin al
Lenguaje de Programacin C

elementos de lenguajes de alto nivel con la flexibilidad y poder de los


ensambladores, permitiendo la manipulacin de bits, bytes y direcciones, a pesar
de ello el cdigo en C es muy portable. Esto le hace particularmente adecuado
para la programacin de sistemas.
Entre sus principales caractersticas, se puede mencionar:

Lenguaje programacin de sistemas (UNIX), es decir es utilizado en para


programar partes del sistema de operacin y/o utilidades, aunque es un
Lenguaje de propsito general.

Lenguaje de nivel intermedio, combina caractersticas de lenguaje de alto


nivel y la flexibilidad de los lenguajes ensambladores.

Un conjunto reducido de palabras reservadas, siendo un lenguaje muy


simple, con funcionalidades aadidas por bibliotecas estndar.

Funcionalidades adicionales (I/O, matemticas, memoria dinmica, etc.)


estn disponible a travs de bibliotecas estndar.

No es un lenguaje fuertemente estructurado, aunque posee estructuras de


control propias de lenguajes estructurado (while, do o for), sin embargo
tiene instrucciones como goto, return, etc.

No es un lenguaje fuertemente tipeado, permite que tipos diferentes, tales


como caracteres y enteros, se mezclen en una expresin. As mismo
permite el uso incongruente de argumentos y parmetros en las llamadas a
funciones.

No comprueba errores durante la ejecucin, es posible que se sobrepasen


los lmites de los arreglos.

Cdigo muy portable, es posible llevar o fcil de adaptar los programas


escritos a otro sistema de operacin o hardware.

Lenguaje conciso con sobrecarga de operadores lo que puede dar a lugar


programas crpticos que pueden atentar contra la claridad.

Usa un lenguaje de preprocesado, el preprocesador de C se usa para


tareas como incluir archivos al cdigo fuente, definir macros y compilacin

Mayo 2013

Introduccin al
Lenguaje de Programacin C

condicional.

Soporta llamado recursivo de funciones.

Incluye apuntadores y aritmtica de direcciones.

Soporta compilacin por separado.

Ofrece solamente el paso parmetros por valor.

Imposibilidad de anidar funciones.

Flujo

de

control

sencillo,

aunque

no

soporta

multiprogramacin,

paralelismo, sincronizacin o corrutinas.


En definitiva el lenguaje C, por sus caractersticas y eficiencia, se ha definido
como un lenguaje para programadores.
Adicionalmente el lenguaje C ha influido a muchos lenguajes de programacin
entre los que se puede mencionar: C++, java, JavaScript, C#, Objective-C, Perl,
PHP, Python entre otros.
Con la aparicin de C++, se pens que C dejara de existir como lenguaje de
programacin, pero no ha sido as en parte inmensa cantidad de sistemas y
aplicaciones en funcionamiento que desarrollada en C necesita mantenimiento,
no siempre se requiere la orientacin a objeto de C++ por ejemplo aplicaciones
empotradas, a tiempo real o que requieran de mucha eficiencia.

Mayo 2013

Introduccin al
Lenguaje de Programacin C

Pasos para la creacin de una aplicacin en lenguaje C


En este nivel debe estar claro, que una computadora solo puede ejecutar
directamente los programas escritos en lenguaje de mquina, el resto hay que
traducirlos. Los programas escritos en lenguajes de alto nivel, se traducen
mediante programas llamados, traductores o procesadores de lenguajes, existen
tres tipos:

Compilador

Intrprete

Compilador-Intrprete

En el caso de una aplicacin o un programa en C, de forma muy simplificada se


tiene algo como:
Programa
Fuente
Hola.c

Compilador
Enlazador
gcc

Ejecutable
a.out

Ahora en detalle, los pasos para la creacin de una aplicacin en C, son las
siguientes:
Crear el programa fuente para lo cual se utiliza un editor.
Compilacin del programa, C proporciona ciertas facilidades del lenguaje
por medio de un preprocesador, que conceptualmente es el primer paso
separado en la compilacin, entre sus funcionalidades se pueden nombrar:
inclusin de archivos, substitucin de macros, compilacin condicional. As
mismo C tiene soporte de compilacin por separado, es decir se un
programa se puede escribir en mltiples archivos y cada uno de ellos
compilado por separado, lo cual tiene como ventaja en que un cambio en
uno de los archivos no requiere la compilacin del programa completo.

Mayo 2013

Introduccin al
Lenguaje de Programacin C

Enlazar los diferentes mdulos objetos, las bibliotecas requeridas y crear


archivo ejecutable
Opcionalmente depurar la aplicacin.
En el caso de aplicaciones medianas o grandes, que involucre muchos
archivos, opciones de compilacin no usuales se cuenta con herramientas,
como make, que dan soporte a proceso de compilacin de forma
automtica y que permite ser muy eficiente en dicho proceso, compilando
solo aquellos archivos que los requieran. Y que no se queden por fuera de
dicho procesos, archivos de programa que aunque ellos no han
cambiando, sin embargo fueron modificados otros de los cuales se tiene
alguna dependencia.
A continuacin se muestra un grafico con un pequeo ejemplo, el cual involucra
una aplicacin que conformada por tres archivos fuentes, uno principal y otros
dos uno de los cuales implementan el TAD cola y el otro los clculos a utilizar en
un modelo de simulacin.

Encabezado

Encabezado

Encabezado

Encabezado

Encabezado

<stdio.h>

colas.h

calculos.h

colas.h

calculos.h

Fuente

Preprocesador

Fuente

Fuente

colas.c

calculos.c

Objeto

Objeto

Objeto

Principal.o

colas.o

calculos.o

Editor

Principal.c
Compilador

Librerias

Enlazador
Ejecutable
[Depurador]

Mayo 2013

miSimulador

Introduccin al
Lenguaje de Programacin C

Ahora todos ellos se compilan por separados y luego se enlazan para producir la
aplicacin miSimulador. Recordemos que el proceso de compilacin se puede
automatizar utilizando la herramienta make, la cual lee las instrucciones y las
dependencias de un archivo (makefile) y ejecuta los comandos que permiten
generar el cdigo ejecutable.
Cuando se escriben programas, se pueden cometer errores (bugs). De hecho, los
programadores comenten errores y la probabilidad de que el programa funcione
a la primera vez es prcticamente cero. Por lo tanto, el desarrollo de un programa
siempre incorpora una etapa de depuracin (debugging), que consiste en buscar
y resolver los errores cometidos durante la programacin. Para facilitar la etapa
de depuracin es conveniente usar herramientas especializadas para estos
efectos. La ms comn es el depurador o tambin llamado debugger.
Un depurador es una herramienta que permite intervenir durante la ejecucin de
un programa, para saber cmo se est ejecutando. Un depurador permite, entre
otras funciones:
Ejecutar paso a paso un programa (stepping).
Establecer puntos de detencin (breakpoints).
Examinar el contenido de las variables y objetos.
Conocer el encadenamiento de llamadas de procedimientos.
Retomar la ejecucin hasta un nuevo punto de detencin.
Este es un buen punto para recordar que en un mundo lleno de complejidades,
se puede perder de vista los principios bsicos:
Simplicidad, mantiene los programas breves y manejables
Claridad, garantizan que sean fciles de entender, tanto para las personas
como para las mquinas
Generalidad, significa que trabajaran bien en una amplia gama de

Mayo 2013

Introduccin al
Lenguaje de Programacin C

situaciones y se adaptaran bien a medida que surjan situaciones nuevas


Automatizacin, que permite que sea la mquina la que el trabajo por
nosotros, liberndonos de tareas mundanas
El propsito del estilo es que el cdigo sea fcil de leer por usted y por los otros, y
resulta crucial para la buena programacin. Escribir un programa es ms que sea
sintcticamente correcto, estn libres de errores y sea muy eficiente.
Los programas no solo son ledos por computadores sino tambin por
programadores, un programa bien escrito es ms fcil de entender y modificar
que uno mal escrito.

Por lo general una buena escritura produce programas

correctos y es algo que no es difcil. El cdigo debe ser claro y sencillo, y evitar
trucos ingeniosos y estructuras poco usuales.
Como ejemplo de lo anteriormente comentado, se puede observar el siguiente
cdigo:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
// Realizar la conversin de notacin decimal a binario
// de un numero entero positivo
int main(int argc, char **argv){
unsigned int n=5,p=1;
unsigned long b=0;
printf("%d",n);
for(;n;n>>=1,p*=10)
b+=p*(n&1);
printf(" en binario es: %lu\n",b);
return 0;
}
/* --- Fin ejemplo --- */

Y compararlo con el siguiente:

Mayo 2013

10

Introduccin al
Lenguaje de Programacin C

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
// Realizar la conversin de notacin decimal a binario
// de un numero entero positivo
int main(int argc, char **argv){
unsigned int n=5,p=1;
unsigned long b=0;
printf("%d",n);
while(n!=0){
b=b+p*(n%2);
p=p*10;
n=n/2;
}
printf(" en binario es: %lu\n",b);
return 0;
}

/* --- Fin ejemplo --- */

Es oportuno el momento, para resaltar que la gua est elaborada de tal forma
que los cdigos de ejemplo son programas que pueden ser ejecutados, lo que se
debe realizar el copiar y pegar en el IDE de su preferencia, ejecutarlos y observar
los resultados. As mismo se invita al lector a jugar con los cdigos
modificndolos, ejecutndolos y explicando los resultados.

Mayo 2013

11

Introduccin al
Lenguaje de Programacin C

Entorno de Programacin Integrado


Un entorno de programacin integrado o en ingls Integrated Development
Environment (IDE) es una aplicacin compuesta por un conjunto de herramientas
para programar, la cual puede estar dedicada de forma exclusiva a un slo
lenguaje de programacin o bien a poder utilizarse para varios.
Un IDE es un entorno de programacin que ha integrado diferentes aplicaciones,
tales como: editores de cdigo, compiladores, depurador, entre otras.
En nuestro caso en particular se ha utilizado el IDE eclipse (http://www.eclipse.org)
y code::block (http://www.codeblocks.org/).
A continuacin se muestra el IDE eclipse, con el programa HolaMundo

Mayo 2013

12

Introduccin al
Lenguaje de Programacin C

De forma similar se muestra el IDE Code::Block

Mayo 2013

13

Introduccin al
Lenguaje de Programacin C

Estructura de un programa en C
Los programas en C pueden estar formados por una o ms funciones, aunque la
nica funcin que debe estar presente en la funcin main(), siendo la funcin que
se invoca de primero cuando el programa se ejecuta, aunque main no es una
palabra clave se trata como si lo fuera, los archivos de los programas en C tienen
extensin .c para los programas o librerias y .h para los encabezados (ya sean del
programador o de las libreras estndares) definiciones de tipos, estructura y
prototipos de las funciones en otros archivos o mdulos.
Aunque un programa en C puede estar formado solamente por construcciones
propias del lenguaje, los compiladores de C incorporan bibliotecas estndar que
proporcionan funciones para algunas de las tareas ms usuales, por ejemplo
entrada y salida ya sea por consola o por archivo, manejo de caracteres y
cadenas de caracteres, funciones matemticas, memoria dinmica, etc.
Ahora, la estructura general de un programa en C, junto con nuestro primer
programa (en el archivo hola.c), se muestra a continuacin
Declaraciones globales
tipo funcin(parmetros){

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/

Declaraciones locales

#include <stdio.h>

secuencia de instrucciones

int main(void){
printf("Hola Mundo\n");
return 0;
}

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

/* --- Fin ejemplo --- */

Declaraciones locales
secuencia de instrucciones
}

Mayo 2013

14

Introduccin al
Lenguaje de Programacin C

La forma de compilar este programa, depende del sistema, en nuestro caso es


desde la lnea de comando con gcc hola.c y se ejecuta con la orden a.out y
siendo su salida
Hola Mundo

En el programa se deben incluir los archivos de encabezados de todas las libreras


o mdulos que se utilicen, sean estndar del lenguaje o del sistema y las creadas
por el usuario. Para incluir un archivo de cabecera del sistema se utiliza la
directiva del preprocesador #include <nombre.h> y para incluir una propia se
utiliza #include nombre.h
Analizando el programa se puede observar que:
Se considera comentario todo lo incluido entre /* y */. Siguiendo el
siguiente formato: /* comentario */ , un comentario puede ocupar varias
lneas y no pueden haber comentarios anidados, adicionalmente C99
permite

comentarios

en

una

sola

lnea

comenzando

con

//

extendindose hasta el final de la lnea por ejemplo // comentario.


#include <nombre_archivo.h> es una directiva para el preprocesador que
incluye un archivo de cabecera (header) en este caso la biblioteca
estndar de entrada y salida.
Se define la funcin main() es la funcin principal del programa, es decir la
primera funcin a la que se llama dentro de la ejecucin del programa y
que las instrucciones estn entre llaves ("{" y "}") .
Se llama a la funcin printf() de la biblioteca estndar de entrada y salida,
la cual muestra la cadena de caracteres "Hello, world\n" en la salida
estndar.

Mayo 2013

15

Introduccin al
Lenguaje de Programacin C

Identificadores
Un mecanismo fundamental de abstraccin en un lenguaje de programacin, es
el uso de nombres o identificadores, para denotar entidades o constructores del
lenguaje.
Un identificador, sirven para nombrar variables, etiquetas, funciones, y otros
objetos definidos por el programador, puede estar compuesto de cualquier
combinacin de letras (minsculas y maysculas), dgitos y el smbolo underscore
'_'. La nica restriccin es que el primer carcter debe ser una letra o un
underscore. Un identificador no puede coincidir con una palabra clave de C y
con identificadores previamente definidos en el mismo mbito.
Ejemplos de identificadores:
Vlidos:
x
y2
suma_1
_t
TABLA
No vlidos:
4num
x
orden-no
ind lis

primer carcter no es letra


carcter ilegal
carcter ilegal espacio ilegal

Observaciones

C es case-sensitive, es decir se diferencia entre maysculas y minsculas.

No

se

limita

la

longitud

de

los

identificadores.

Pero

algunas

implementaciones slo reconocen (son significativos) los 8 primeros y otras


(ANSI) los 31 primeros caracteres.

Mayo 2013

16

Introduccin al
Lenguaje de Programacin C

Palabras reservadas (C89)


Las palabras reservadas de C, que no pueden ser utilizadas en definiciones por el
usuario son las que se listan en la siguiente tabla:
auto

double

int

struct

break

else

long

switch

case

enum

register

typedef

char

extern

return

union

const

float

short

unsigned

continue

for

signed

void

default

goto

sizeof

volatile

do

if

static

while

_Bool

_Complex

A las cuales C99 aade, entre otras:


inline

restrict

_Imaginary

Mayo 2013

17

Introduccin al
Lenguaje de Programacin C

Tipos de datos
C utiliza 5 palabras reservadas para definir los tipos de datos fundamentales. A
diferencia de otros lenguajes, un determinado tipo de datos puede ir cualificado
por un conjunto de modificadores.
Los tipos de datos fundamentales son:
char

carcter

int

entero

float

real

double

real doble precisin

void

sin tipo

Todos los dems tipos se basan en los anteriores

En este punto es interesante observar que a diferencia de otros muchos lenguajes


de programacin, C no tiene como tipos de datos fundamentales las cadenas de
caracteres o string y el tipo lgico o boolean. Para el caso de las cadenas se
utilizaran arreglo de caracteres, como se estudiara posteriormente, y en el caso
del tipo de dato lgico (boolean) se suele utilizar un entero, interpretndose todo
valor distinto de 0 como verdadero y el valor 0 como falso.

Modificadores
A excepcin del tipo void, los tipos de datos bsicos pueden tener diferentes
modificadores precedindolos, que pueden alterar su significado ajustndolo ms
a las necesidades del programador, a continuacin se muestra la lista de
modificadores:
signed

con signo

unsigned

sin signo

Mayo 2013

18

Introduccin al
Lenguaje de Programacin C

short

corto

long

largo

Cuando se utilizan un modificador de tipo por si solo, es decir sin preceder a


ningn tipo bsico, se asume como entero y por lo general los nmeros enteros
negativos se representa en complemento a dos
A continuacin se muestra una tabla con los tipos, su tamao en bits y el rango
de valores que puede almacenar, hay que tener siempre presente sobre todo por
consideraciones de portabilidad, que esto puede variar por cada tipo de
procesador.
Tipo

Tamao Bits

Rango de valores

char

-128 a 127

unsigned char

0 a 255

signed char

-128 a 127

int

16 (o 32)

-32.768 a 32.767

unsigned int

16 (o 32)

0 a 65.535

signed int

16 (o 32)

-32.768 a 32.767

short int

16

-32.768 a 32.767

unsigned short int

16

0 a 65.535

signed short int

16

-32.768 a 32.767

long int

32

-2.147.483.648 a 2.147.483.647

unsigned long int

32

0 a 4.294.967.295

signed long int

32

-2.147.483.648 a 2.147.483.647

long long int

64

Aadido por C99

unsigned long long int

64

Aadido por C99

enum

16

0 a 65.535

float

32

3,4E-38 a 3,4E+38 (7 dgitos)

double

64

1,7E-308 a 1,7E+308 (15 dgitos)

long double

64

1,7E-308 a 1,7E+308 (15 dgitos)

Mayo 2013

19

Introduccin al
Lenguaje de Programacin C

Se pueden definir nuevos nombre para los tipos de datos existentes utilizando la
palabra clave typedef, que realmente no crea un nuevo tipo de datos sino que
define un nuevo nombre para un tipo ya existente. La forma de utilizarlos es:
typedef tipo nombre;
Donde tipo es cualquier tipo de datos valido, ya sea un tipo base o una
estructura, por ejemplo:
typedef unsigned char byte;
El programa a continuacin muestra el tamao de las diferentes tipos, para lo
cual usaremos el operador sizeof que calcula el tamao, en bytes, de cualquier
tipo o variables.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int a;
float f;
printf("Size
printf("Size
printf("Size
printf("Size
printf("Size
printf("Size
printf("Size
printf("Size
return 0;

of
of
of
of
of
of
of
of

char: %d\n",sizeof(char));
short: %d\n",sizeof(short));
int: %d\n",sizeof(int));
long int: %d\n",sizeof(long int));
float: %d\n",sizeof(float));
double: %d\n",sizeof(double));
a: %d\n",sizeof(a));
f: %d\n",sizeof(f));

}
/* --- Fin ejemplo --- */

Mayo 2013

20

Introduccin al
Lenguaje de Programacin C

Variables, alcance y tiempo de vida


Una variable es un objeto cuyo valor almacenado puede cambiar durante la
ejecucin, algo como la posicin de memoria con un nombre que se utiliza para
mantener un valor que puede ser modificado durante la ejecucin del programa.
Tambin se puede pensar en una variable, completamente especificada por sus
atributos, que incluyen su nombre o identificador, su localizacin, su valor y otros
atributos como tipo de datos y tamaos.
Otros
Atributos

Nombre

Valor
Localizacin

El nombre o identificador es el smbolo que la denota.

El tipo define lo que puede almacenar la variable y el conjunto de


operaciones que pueden aplicar

Los valores son cualquier cantidad almacenable, como enteros y reales


llegando incluso a valores matriciales formados por una secuencia de
valores almacenados en cada unos de los ndices de matriz.

La localizacin son lugares donde se pueden almacenar los valores, son


como las direcciones en la memoria computadora, pero podemos pensar
en ellas de una manera ms abstracta que las direcciones de una
computadora en particular. Las declaraciones no son la nica forma de
asociar nombres con localizaciones.

Se entiende como atributos principales de una variable el nombre, la localizacin


y su valor, por lo podemos imaginar una variable como

Nombre

Valor
Localizacin

A esto se le llama un diagrama de cuadro y circulo.

Mayo 2013

21

Introduccin al
Lenguaje de Programacin C

Por ejemplo para la declaracin


int n = 123;
Que declara a n como una variable entera con valor 123

123

Otras definiciones importantes relacionadas con las variables, son:

Un binding o ligadura es el proceso de asociacin de atributo


(propiedades) a un nombre (identificador), por ejemplo un nombre de
variable con su localizacin.

Tiempo de vida de una variable: El tiempo de vida se refiere al intervalo de


tiempo que trascurre desde que se crea la variable hasta que se destruye.

Alcance de una variable: El alcance de una variable es el conjunto de


instrucciones en la que esa variable es visible por medio de su identificador.

Es importante entender la diferencia entre alcance y tiempo de vida de una


variable. Si una variable no es visible, no necesariamente ha sido destruida. En
cambio, si una variable fue destruida, esa variable no es visible.
La forma principal en que una variable cambia su valor es la asignacin, por
ejemplo x = e, donde x es el nombre de una variable y e es una expresin, donde
la semntica es que se evala e a un valor, que a sus vez se copia en la
localizacin de x. En el caso de que e sea el nombre de una variable, digamos y,
se tiene que:
x = y;
Dado que una variable tiene una localizacin y un valor almacenado en dicha
localizacin, y es importante distinguir claramente entre ambos. Sin embargo en
una asignacin esta distincin se oscurece; el lado derecho representa el valor de

Mayo 2013

22

Introduccin al
Lenguaje de Programacin C

y en tanto que el x del lado derecho representa la localizacin de x. Por esta


razn el valor almacenado en una localizacin de una variable se le conoce
como rvalue (por el valor del lado derecho) y en tanto que la localizacin de una
variable se le conoce como lvalue (por el valor del lado izquierdo).
Frecuentemente se encuentra en los manuales del lenguaje C y en los mensajes
de error del compilador los trminos rvalue y lvalue, en trminos prcticos un
lvalue significa algo a que se le puede asignar (indica que estaba al lado
izquierdo del operador de asignacin) y un rvalue significa el valor de una
expresin (aparece a derecha de la asignacin). La nocin de lvalue y rvalue
fueron introducidas por el lenguaje de programacin CPL en los aos sesenta.

Mayo 2013

23

Introduccin al
Lenguaje de Programacin C

Tipos de variables
Un programa compilado en C tiene cuatro regiones lgicas de memoria
diferentes, cada una de ellas para propsitos especficos, las cuales se muestran
a continuacin:

Aunque la disposicin fsica de cada una de ellas puede diferir entre los diferentes
tipos de procesadores y entre las diferentes implementacin del lenguaje. La
figura anterior muestra de forma conceptual como aparece un programa en C
en la memoria. La primera regin contiene el cdigo del programa, en la
siguiente regin se guardan las variables globales (datos estticos) ambas
regiones se asignan en tiempo de compilacin. Las dos regiones restante son
asignadas en tiempo de ejecucin y son la pila (stack) y el montn (heap), la pila
mantiene entre otros las direcciones de retornos, los parmetros reales y las
variables locales (datos automticos) y finalmente el montn es la regin que
puede utilizarse, de forma explcita, mediante las funciones de administracin de
memoria dinmica (datos dinmicos) y se utilizan a travs de apuntadores
(pointers).

Mayo 2013

24

Introduccin al
Lenguaje de Programacin C

Declaracin de variables
La forma general de declaracin es:
<tipo> lista_de_variables;
int numero1, numero2;
long int l;
Las variables globales y static solo son inicializadas al principio del
programa, las variable locales automticas se inicializan cada vez que se
entra en el bloque. Las variables globales y static que no hayan sido
inicializadas toman automticamente el valor inicial de cero y las locales
auto tendrn valores desconocidos.

Inicializacin de variables en la declaracin


El esquema para la inicializacin de variables en la declaracin es el siguiente:
<tipo> nombre_variable = valor;
int numero1=5,numero2;

Dnde se declaran las variables


Bsicamente hay tres sitios donde se pueden declarar variables: dentro de las
funciones, en la definicin de los parmetros de las funciones y fuera de todas las
funciones. Estas variables se denominan, respectivamente, variables locales, los
parmetros formales y variables globales.

Variables locales, parmetros formales y variables globales


El lugar donde se declara una variable define el mbito que determina el
alcance o visibilidad de la variable por medio de su identificador. Hay que

Mayo 2013

25

Introduccin al
Lenguaje de Programacin C

recordar que dentro del mismo mbito no se pueden realizar declaraciones con
el mismo identificador

Variable local: A las variables locales que se declaran dentro de una


funcin nos referimos a ellas como variables automticas. Solo puede ser
utilizada dentro del bloque en el que han sido declaradas o expresado de
otra forma, las variables locales no son conocidas fuera del bloque de
cdigo donde han sido declaradas. Un bloque de cdigo comienza con
una llave que abre { y termina con una llave que cierra }, se pueden
declarar variables locales en cualquier bloque, el bloque definido por una
funcin es solo un caso especial. Las variables locales solo existen mientras
se est ejecutando el bloque de cdigo donde est declarada, es decir se
crean al entrar y destruyen a salir de l y su valor se pierde, esto es
particularmente importante en las llamadas a funciones ya que no pueden
retener su valor entre llamadas, sin embargo se usando el calificador static
se crea un almacenamiento permanente con alcance en el bloque.

Parmetros formales: Si una funcin utiliza argumentos, debe declarar las


variables que aceptarn los valores de los argumentos, esas variables son
los parmetros formales de la funcin y se comportan como cualquier otra
variables local de la funcin. Hay que tener presente que al igual de las
variables locales son automticas y se destruyen al salir de la funcin.

Variables globales: A diferencia de las variables locales, las variables


globales se conocen a lo largo del todo programa y se puede utilizar en
cualquier parte del cdigo, adems mantienen sus valores durante toda la
ejecucin del programa. Son variables que declaran fuera de todas las
funciones.

En la prctica ocurre que cada identificador solo tiene alcance (es visible) en
algunas regiones de su mbito, que podran ser discontinuas. La razn por la que
un identificador deja de tener alcance (o ser visible) dentro de su mbito es que
sea ocultado por otra declaracin explcita que utiliza el mismo identificador. La

Mayo 2013

26

Introduccin al
Lenguaje de Programacin C

nueva declaracin puede ocurrir por ejemplo en un bloque de cdigo anidado


(recordemos en el mismo no es posible una nueva declaracin con el mismo
identificador) o dentro de una funcin en el caso de variables globales.
Como se pudo observar dependiendo del sitio donde se declaren las misma
pueden tener distintos tiempo de vida, recordemos si una variable no es visible, no
necesariamente ha sido destruida. En cambio, si una variable fue destruida, esa
variable no es visible.
En el siguiente ejemplo se pueden observar todos los sitios donde se declaran las
variables, en ellas se puede observar conceptos como mbito y alcance.

#include <stdio.h>
int numero1, numero2;

Variable Global

int funcion1(int numero1,int numero2){

Parmetro Formal

}
int funcion2(void){
int numero1, numero2;

Variable local

}
int funcion3(void){
int numero1, numero2;
if (numero1==numero2){
int numero1, numero2;

Variable Local (Bloque)

}
}
A continuacin se muestra un ejemplo donde se pueden observar los conceptos
de mbito y alcance de las variables.

Mayo 2013

27

Introduccin al
Lenguaje de Programacin C

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int a=0;
void funcion1(int a){
printf("En funcion1 el valor de a:%d\n",a);
}
void funcion2(int p){
int a=p;
printf("En funcion2 el valor de a:%d\n",a);
funcion1(a+1);
}
int main(void){
int a=1;
printf("En main el valor de a:%d\n",a);
funcion2(a+1);
return 0;
}
/* --- Fin ejemplo --- */

mbitos de un programa en C
En C los trminos local y global se utilizan para describir, en forma general, la
diferencia entre identificadores que se declaran entre un bloque y los que se
declaran fuera de todos los bloques.
Sin embargo en C de definen de forma ms especifica esas categoras, el
estndar define cuatro mbitos que determinan la visibilidad de un identificador,
los cuales se describen a continuacin:

mbito de archivo, comienza al principio del archivo (unidad de


traduccin) y termina al final del mismo. Se refiere a todos los
identificadores que se encuentran fuera de todas las funciones, estos
identificadores son visibles en todo el archivo. Las variables que tienen un
mbito de archivo son globales.

Mayo 2013

28

Introduccin al
Lenguaje de Programacin C

mbito de bloque, Comienza en { de apertura de un bloque y termina con


el correspondiente } de cierre. Las variables con mbito de bloque son
locales a ese bloque. Sin embargo, el mbito de bloque tambin alcanza
los parmetros formales en una definicin de funcin, es decir los
parmetros de la funcin se incluyen en el bloque de una funcin.

mbito de prototipo, los identificadores declarados dentro del prototipo de


una funcin solo son visibles dentro del prototipo.

mbito de funcin, comienza con { de apertura de una funcin y termina


con su correspondiente }. El mbito de funcin solo se aplica a etiquetas,
una etiqueta utilizada como destino de una instruccin goto debe
encontrase en la misma funcin de la instruccin goto.

Calificadores de acceso
Controlan las formas que se acceden o se modifican las variables.
const
No pueden ser modificadas por el programa, solo inicializar.
const int a=10;
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void nocambiar(const char parametro){
printf("desde no cambiar p:%d\015",parametro);
}
int main(void){
const unsigned char b=0xFF;
nocambiar(b);
printf("%d\n",b);
return 0;
}

Mayo 2013

29

Introduccin al
Lenguaje de Programacin C

/* --- Fin ejemplo --- */

volatile
El valor de una variable puede cambiar por medios no explcitamente
especificados por el programa. por ejemplo una direccin de una variable
se le paso a una rutina que maneja un timer o puerto de entrada y salida,
en este caso el valor de la variable puede ser cambiado sin una instruccin
de asignacin explicita del programa. Esto puede ser importante de
notificar al compilador para efecto de optimizacin, ya que el mismo
puede asumir que la variable no cambia.
Se puede utilizar const y volatile junto, por ejemplo un puerto en la
direccin 30H y cuyo valor puede cambiar exclusivamente por una
condicin externa.
const volatile char *puerto = (const volatile char *) 0x30;

Calificadores de clase de almacenamiento


Indican al compilador como deben almacenar las variables.
extern
Especfica (declara) que un objeto esta declarado con enlace externo en
otro mdulo (archivo) del programa, es decir est definido en otro archivo.
int x,y;

extern int x,y;

char c;

extern char c;

int main(){

void func23(void){

x=123;
}

Mayo 2013

y=10;
}

30

Introduccin al
Lenguaje de Programacin C

static
Cuando es variable local se crea un almacenamiento permanente, con
alcance en el bloque que es declarada y cuando la variable es global se
le indica que solo es conocida en el archivo que se declara.

int veces(void){

static int cuentas=0;

static cuentas=0;
int veces(void){
cuentas++;

cuentas++;

return cuentas;

return cuentas;

A continuacin se muestra un ejemplo de compilado por separado, note


que se trata de dos archivos, revise la documentacin del compilador
para compilar y enlazar ambos mdulos.

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*
* archivo: modulo1.c
*/
#include <stdio.h>
#include <stdlib.h>
extern int valor;
void funcion1(void);
int cuenta(void){
static int cuentas=0;
cuentas++;
return cuentas;
}

Mayo 2013

31

Introduccin al
Lenguaje de Programacin C

int main(void) {
funcion1();
printf("valor: %d\n",valor);
printf("cuentas: %d\n",cuenta());
printf("cuentas: %d\n",cuenta());
return EXIT_SUCCESS;
}
/* --- Fin archivo modulo1.c --- */

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*
* archivo: modulo2.c
*/
#include <stdio.h>
#include <stdlib.h>
int valor=5;
void funcion1(void){
printf("desde funcion1 valor: %d\n",valor);
}
/* --- Fin archivo modulo2.c --- */

register
Se le pide al compilador que mantenga el valor en un registro del CPU en
lugar de la memoria, donde normalmente se almacenan las variables, esto
con el fin de realizar operaciones mucho ms rpido.
register int temp;
A continuacin se muestra un ejemplo del uso de register

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>

Mayo 2013

32

Introduccin al
Lenguaje de Programacin C

int main(void){
register char c='a';
for(;c<='z';c++)
printf("%c",c);
return 0;
}
/* --- Fin ejemplo --- */

auto
Utilizado para declara variables locales, sin embargo todas las variables
que no son globales, se asumen auto.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void funcion1(void){
auto int a=1;
printf("En funcion1 el valor de a:%d\n",a);
a=a+1;
}
void funcion2(void){
static int a=1;
printf("En funcion2 el valor de a:%d\n",a);
a=a+1;
}
int main(void){
funcion1();
funcion1();
funcion1();
funcion2();
funcion2();
funcion2();
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

33

Introduccin al
Lenguaje de Programacin C

Constantes
Refieren a valores fijos que no pueden ser modificados por el programa, tambin
se le conocen como literales, pueden ser de cualquier tipo bsico de datos. La
forma que se representa cada constate depende de su tipo.
Enteras:
123
-123
012

/* en octal 10 */

0xA

/* en hexadecimal 10 */

3500L

/* long int */

10000U

/* unsigned int */

Reales:
123.45
1.15f

/* float */

1001.2L

/* long double */

47e-4
.25E7
Caracteres:
Los caracteres imprimibles se escriben entre apostrofes:
'a'
'Z'
Para ls no imprimibles se utiliza \

Mayo 2013

'\n'

/* salto de lnea */

'\r'

/* retorno carro */

'\f'

/* salto de pgina */

34

Introduccin al
Lenguaje de Programacin C

'\t'

/* tabulador */

'\b'

/* espacio atrs */

'\v'

/* tabulador vertical */

'\\'

/* barra invertida */

'\''

/* comillas simples */

'\'

/* comillas dobles */

'\Const'

/* constante octal */

'\xConst'

/* constante hexadecimal*/

Enumeradas
enum dias{Domingo, Lunes, Martes, Miercoles, Jueves,
Viernes, Sabado};
Las enumeraciones son un conjunto de constantes enteras con un nombre
y el valor del primer smbolo en la enumeracin es 0 y cada smbolo
restante recibe un valor que es mayor en 1 que el smbolo que lo precede.
Se puede especificar el valor de uno o ms smbolos utilizando un
inicializador, a los smbolos que le siguen a uno inicializado se le asignan
valores consecutivos.
enum colores {amarillo = 1, azul, rojo, verde=10,
magenta, naranja};
Ahora el valor de estos smbolos son:
amarillo

azul

rojo

verde

10

magenta

11

naranja

12

Un error comn sobre las enumeraciones es que pueden escribirse


directamente, hay que recordar por ejemplo que Verde es el nombre de
un entero.
Cadenas de caracteres (string)
"HOLA MUNDO"

Mayo 2013

35

Introduccin al
Lenguaje de Programacin C

Una cadena de caracteres (string) es un vector de caracteres que termina


con un carcter

'\0', hay siempre que recordar que Las funciones que

manipulan strings esperan que los mismos terminen en '\0'.

Mayo 2013

36

Introduccin al
Lenguaje de Programacin C

Operadores y expresiones
El lenguaje C es sumamente rico en operadores incorporados, entre los que se
tienen:
Asignacin
A diferencia de muchos otros lenguajes en C la asignacin es un
operador y no una instruccin.
Lvalue = expresin
Num = 5
Asignaciones mltiples, se puede asignar a muchas variables el mismo
valor utilizado asignaciones mltiples en una sola instruccin, por
ejemplo:
x = y = z = 0
Recordemos que al ser la asignacin una expresin, se puede utilizar en
cualquier expresin.
c = (a = 4) + (b = 5);
Cuando se mezcla variables de diferentes tipos en una expresin de
asignacin, la regla de conversin es que el lado derecho de la
asignacin se convierte al tipo del lado izquierdo. En caso de enteros a
caracteres o enteros largos a enteros, se pierden los bits ms
significativos, ahora en el caso de flotantes a caracteres o enteros se
asigna la parte entera y en el caso de float a double y double a long
double se puede tener una posible prdida de precisin resultando del
redondeo. En el caso de conversiones de int a float, de float a double y
similares solo se cambia el tipo de representacin sin aadir precisin.

Mayo 2013

37

Introduccin al
Lenguaje de Programacin C

Aritmticos
Negacin

-x

Suma

x+y

Substraccin

x-y

Multiplicacin

x*y

Divisin

x/y

Modulo

x%y

Los operadores aritmticos, operan como en la mayora de los lenguajes


de programacin y se pueden aplicarse a la mayora de los tipos de
datos predefinidos. Cuando se aplica la divisin a enteros o caracteres
se aplica la divisin entera.
El operador modulo obtiene el resto de una divisin entera por lo que no
puede aplicarse a los tipos reales.

Relacinales
Igual

==

x==y

Diferente

x!=y

Mayor que

>

x>y

Mayor o igual que >=

x>=y

Menor que

x<y

<

Menor o igual que <=

x<=y

Las expresiones relacionales y las lgicas devuelven 1 para cierto y 0


para falso.

Mayo 2013

38

Introduccin al
Lenguaje de Programacin C

Lgicos
Negacin

!x

&&

x&&y (Evaluacin en cortocircuito)

||

x||y (Evaluacin en cortocircuito)

La tabla de verdad de los operadores lgicos, para Falso (F) y


Verdadero (V), se muestra a continuacin:
p

p&&q

p||q

!p

Bits
Complemento

~x

And

&

x&y

Or

x|y

Xor

x^y

Corrimiento der.

>>

x>>y

Corrimiento izq.

<<

x<<y

(negacin)

Las operaciones a nivel de bit se refieren a operaciones sobre los bits


que componen un byte o una palabra, que se corresponde con los tipos
char e int y sus variantes, por lo que no pueden utilizarse sobre reales u
otros tipos complejos.
Los operadores de corrimiento desplazan todos los bits, a la derecha o a
la izquierda, y a medida que se desplazan a un extremo se van
rellenando con ceros por el extremo opuesto (en el caso de un entero

Mayo 2013

39

Introduccin al
Lenguaje de Programacin C

negativo que se desplaza a la derecha, hace que entre un 1 para


preservar el signo). Hay que tener en cuenta que un desplazamiento no
es una rotacin, los bits que salen se pierden.
A continuacin, se tiene la tabla de verdad para los operadores de bits
p

p&q

p|q

p^q

~p

Asignacin Compuesta
x=x+y

+=

x+=y

-=

x-=y

*=

x*=y

/=

x/=y

%=

x%=y

&=

x&=y

|=

x|=y

^=

x^=y

>>=

x>>=y

<<=

x<<=y

Incrementales y decrementales
x=x+1

++

x++
++x

x=x-1

--

x---x

Mayo 2013

40

Introduccin al
Lenguaje de Programacin C

El operador ++ aade 1 y el resta 1, los operadores de incremento y de


decremento pueden preceder o seguir al operando existiendo
diferencias entre ellas. Cuando el operador precede a su operando se
lleva a cabo la operacin (de incremento o de decremento) antes de
utilizar su valor del operando, ahora si el operador sigue al operando, se
utiliza su valor antes de incrementarlo o decrementarlo.

Miscelneos
Condicional

x?y:z

Direccin

&

&x

Indireccin

*x

Coma

x,y

Tamao

sizeof()

sizeof(X)

Selector campo

x.y

Selector campo

->

x->y

Elemento arreglo

[]

x[y]

Conversin tipo

(tipo)

(tipo)x

equivale a (*x).y

En este punto hay prevenir al lector de un error comn en C, es confundir


el operador asignacin = con el operador relacional de igualdad ==
No es lo mismo
if (a = 0)

// Asigna a a cero y siempre es falso

Que
if (a == 0) // pregunta por si a es igual a cero
Adicionalmente esta ltima, se puede escribir como
if(!a) // pregunta por si a es igual a cero

Mayo 2013

41

Introduccin al
Lenguaje de Programacin C

Precedencia y Asociacin de operadores


La siguiente tabla resume las reglas de precedencia y asociatividad de todos los
operadores, estn colocados por orden de precedencia decreciente.
Precedencia

Operador

Asociatividad

MAYOR

() [] -> .

Izq. A Der.

~ ++ -- - (tipo) * & sizeof

Der. A Izq.

Unario

*/%

Izq. A Der.

Multiplicativo

+-

Izq. A Der.

Aditivo

<< >>

Izq. A Der.

Corrimiento

< <= >= >

Izq. A Der.

Relacional

== =

Izq. A Der.

Igualdad

&

Izq. A Der.

And bits

Izq. A Der.

Xor bits

Izq. A Der.

0r bits

&&

Izq. A Der.

And Lgico

||

Izq. A Der.

Or Lgico

Der. A Izq.

Condicional

= += -= *= /= %= <<= >>= &= |= ^=

Der. A Izq.

Asignacin

Izq. A Der.

Coma

MENOR

Nombre

Evaluacin en Cortocircuito
En relacin con los operadores lgicos && y || son evaluados de izquierda a
derecha y la evaluacin se detiene tan pronto se conoce el resultado ya seas
falso en los and (&&) y verdadero en los or (||), es decir se realiza una evaluacin
en cortocircuito.

Mayo 2013

42

Introduccin al
Lenguaje de Programacin C

La evaluacin en cortocircuito podra tener efectos colaterales sin embargo se


pueden mencionar dos beneficios importantes:

Se considera una optimizacin ya que en la mayora de los casos ahorra


bastante trabajo en la evaluacin expresiones.

Una expresin relacional se puede utilizar para proteger una operacin


potencialmente insegura en una segunda expresin, por ejemplo, en la
expresin (n != 0) && (x < 1 / n) nunca se podr producir un error de divisin
entre 0 debido a que si por alguna razn n es igual a 0, el operando de la
izquierda (n!=0) se hace falsa y por lo tanto el operador de la izquierda no
se evala.
Muchos de los programas en C se basan en esa propiedad, por ejemplo

for(i=0;i<tamano && (c=getchar())!=EOF); i++)


buffer[i]=c;

Es decir antes de leer se verifica que hay espacio en el buffer.

A continuacin se muestran varios programas que ejemplifican el uso de usos


de diferentes operadores:

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i,j,k=0;
i=j=1;
printf("i:%d j:%d k:%d\n",i,j,k);
printf("i+=2:%d j-=1:%d \n",i+=2,j-=1);
i=j=1;
printf("i:%d j:%d \n",i,j);
printf("i++:%d ++j:%d \n",i++,++j);

Mayo 2013

43

Introduccin al
Lenguaje de Programacin C

printf("i>2:%d j==2:%d !k:%d\n",i>2,j==2,!k);


printf("(i=5,3+4):%d\n",(i=5,3+4));
printf("(i=1,j=(i==1?i*i:i+i)):%d\n",(i=1,j=(i==1?i*i:i+i)));
printf("Cuidado\n");
i=j=1;
printf("i:%d j:%d \n",i,j);
printf("(i==1||i++):%d\n",(i==1||i++));
printf("(j!=1&&++j):%d\n",(j!=1&&++j));
printf("Evitar\n");
printf("i:%d j:%d \n",i,j);
printf("(i=1,i=2?i*i:i+i):%d\n",(i=1,i=2?i*i:i+i));
printf("i:%d j:%d \n",i,j);
i=j=1;
printf("i:%d j:%d \n",i,j);
printf("(i---j):%d\n",(i---j));
printf("i:%d j:%d \n",i,j);
i=5;
j=4;
printf("i:%d j:%d \n",i,j);
printf("(i>j?i:j):%d\n",(i>j?i:j));return 0;
}
/* --- Fin ejemplo --- */

Evaluacin en cortocircuito
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
int ia[] = {2,4,7,10,14,16,20,24,25,30,35};
int busquedaSecuencialOrdenado(int value,int array[], int size){
register int i;
for(i=0; i<size && array[i]<value; i++);
if(i<size && value==array[i])
return i;
return -1;
}
int main(void){
printf("esta en %d\n",busquedaSecuencialOrdenado(20,ia,11));
return 0;
}

Mayo 2013

44

Introduccin al
Lenguaje de Programacin C

/* --- Fin ejemplo --- */

Trabajando con bits


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#define SET(B,S) (B|=1<<S)
#define CLEAR(B,S)(B&=~(1<<S))
#define GET(B,S)(B>>S&1)
int main(void){
unsigned char b=0;
printf("%d\n",b);
SET(b,0);
printf("%d\n",b);
SET(b,2);
printf("%d\n",b);
CLEAR(b,0);
printf("%d\n",b);
printf("Get 2: %d\n",GET(b,2));
CLEAR(b,2);
printf("Get 2: %d\n",GET(b,2));
printf("%d\n",b);
SET(b,5);
printf("%d\n",b);
return 0;
}
/* --- Fin ejemplo --- */

Otros usos interesantes de los operadores de bits


Determinar si un nmero es par
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i;
printf("Ingrese un entero\n");

Mayo 2013

45

Introduccin al
Lenguaje de Programacin C

scanf("%d",&i);
printf("%d es %s\n",i,i&1?"Impar":"Par");
return 0;
}
/* --- Fin ejemplo --- */

Dividir entre dos un nmero entero


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i;
printf("Ingrese un entero\n");
scanf("%d",&i);
printf("%d/2 %d\n",i,i>>1);
return 0;
}
/* --- Fin ejemplo --- */

Operadores coma y condicional

En relacin al control de flujo, en C, se destacan los operadores:


x,y

(operador coma), un par de expresiones separadas por coma


se evalan de izquierda a derecha y el valor de la izquierda se
descarta, el tipo y valor del resultado es el de la derecha.

x?y:z (operador condicional), se evala la primera expresin, si es


diferente a cero, el resultado es la segunda expresin, sino es
la tercera expresin. Evaluando uno solo de los operandos
segundo o tercero.
A continuacin se muestra un ejemplo del uso de estos operadores

Mayo 2013

46

Introduccin al
Lenguaje de Programacin C

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i,j;
for(i=0,j=10;i<j;i++,j--)
printf("Maximo %d\n",i>j?i:j);
return 0;
}
/* --- Fin ejemplo --- */

Expresiones
Una expresin es una sucesin de operadores y operandos debidamente
relacionados, las expresiones combinan variables, constantes y llamadas a
funciones para producir nuevos valores, especificando los operadores lo que va a
ser realizado. Los operandos de diferente tipos que aparecen en una expresin se
convierten a un mismo tipo, tal cual como se especifica a continuacin.
Conversin de tipo:
Implcita se realiza automticamente por el compilador y a esta operacin
se le denomina promocin:
En una asignacin se convierte el tipo al lvalue.
En una expresin todos se convierte a un nico tipo, usando el criterio de
convertirlos todos al tipo del mayor Tamao
char o short int
unsigned char o unsigned short unsigned
int unsigned long unsigned long float double

Mayo 2013

47

Introduccin al
Lenguaje de Programacin C

Explicita: se realiza a travs uso del operador cast, es decir la solicita


especficamente el programador:
c = '0' + (char)num;
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int a=2,b=3;
float p;
p=(a+b)/2;
printf("%f\n",p);
p=(float)(a+b)/2;
printf("%f\n",p);
p=(a+b)/2.0;
printf("%f\n",p);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

48

Introduccin al
Lenguaje de Programacin C

Instrucciones (sentencias ejecutables)


En sentido ms general las instrucciones es una parte del programa que se puede
ejecutar, es decir, una instruccin (Sentencia o Proposicin) especifica una
accin. En C las estructuras de control son sencillas (y familiares para
programadores que ya conozcan Pascal o cualquier otro lenguaje de
programacin de alto nivel), permiten agrupar instrucciones, tomar decisiones (ifelse), seleccionar entre varias posibilidades (switch), hacer bucles (iteraciones)
evaluando la condicin al empezar (while, for) o al acabar (do), etc.
En C hay cuatro tipos de instrucciones:
Las de expresin.
Las de bloques.
De etiqueta.
Las de control de flujo.
Instrucciones de expresin
Las instrucciones de expresin son aquellas en las que se especifica una expresin
vlida seguida de un ;.
A=5*6+8;
a+=b=1;
m=x>y?x:y;
Una instruccin de este tipo puede ser la llamada a una funcin seguida de ;.
printf("Hello, world\n");

O la instruccin vaca
;
Instrucciones de bloques
Los bloques comienzan con una llave que abre y acaban con una llave que

Mayo 2013

49

Introduccin al
Lenguaje de Programacin C

cierra, conteniendo en su interior en primer lugar las posibles declaraciones


(locales al mbito del bloque) y a continuacin una lista de instrucciones.
{
int i=0,j=1;
if(i && ++j)
printf("Entro\n");
printf("Valor de i:%d j:%d\n",i,j);
}
Observe que No hay ; luego de la } que cierra el bloque.
En C99 se permite intercalar declaraciones e instrucciones dentro de un bloque.
{
int i;
i=2;
int j; // esta declaracion no es valida en C89
j=i*3;
printf("Los valores de i:%d y j:%d\n",i,j);
}
Instrucciones de etiqueta
La instruccin goto necesita de una etiqueta para operar, una etiqueta es un
identificador seguido de : y pueda estar adherida a cualquier instruccin en la
misma funcin en la que est el goto, es decir el alcance de un goto es la funcin
y no se puede saltar entre funciones.
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(x[i]==y[j])
goto iguales;
...
iguales:
...
El cdigo que involucra goto por lo general es ms difcil de entender y
mantener, adicionalmente se puede escribir cdigos equivalentes sin l, aunque
tal vez con el precio adicional de variables extras y/o instrucciones de control

Mayo 2013

50

Introduccin al
Lenguaje de Programacin C

adicionales.
/*
* UCAB - Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
int main(void){
int i=0;
printf("Inicio\n");
while(1){
for(;;){
if(i==10) goto salir;
printf("\tValor i:%d\n",i);
i++;
}
}
salir:
printf("Fin\n");
return 0;
}

Instrucciones de control de flujo


Van a permitir controlar el flujo de la ejecucin de instrucciones, es decir
especifican el orden en que se realiza el procesamiento, y se clasifican en:
Secuencia
Las de seleccin
Las de iteracin
Las de salto
Secuencia
En C el ; es un terminador de instruccin no un separador como en otros
lenguajes como Pascal. En C las instrucciones se ejecutan una despus de
la otra, en el orden en que estn escritas, es decir, en secuencia.

Mayo 2013

51

Introduccin al
Lenguaje de Programacin C

m=x>y?x:y;
tasa = 0.15 * pago;
; /* instruccion vacia */
Seleccin
C contempla los if y el switch como instrucciones de seleccin.
if(exp)
instruccin
+

En el if, si la expresin exp es verdadera se ejecuta la instruccin,


que puede ser una instruccin sencilla (incluyendo la vaca) o de
bloque.
if (estado == 'P')
tasa = 0.17 * pago;

Mayo 2013

52

Introduccin al
Lenguaje de Programacin C

if(exp)
instruccin (verdadero)

else
instruccin (falso)

En el if-else, si la expresin es verdadera se ejecuta la instruccin


(verdadero) en caso contrario se ejecuta la instruccin (falso).
if (estado == 'P')
tasa = 0.17 * pago;
else
tasa = 0.25 * pago;
Los if se pueden anidar, es decir if dentro de if, en C89 se especifican
al menos 15 niveles de anidamiento. En if anidados el else se asocia
con el if ms prximo que ya no est asociado.
switch(exp){
case valor:
instrucciones

case valor:
instrucciones

+
+

[default:

instrucciones]
}
El switch es una instruccin de seleccin mltiple, que compara el
resultado de una expresin exp con una lista de valores (enteros o

Mayo 2013

53

Introduccin al
Lenguaje de Programacin C

de carcter) especificada por los case en orden, cuando se


encuentra

la

correspondencia

se

ejecutan

las

instrucciones

asociadas con ese case, hasta que se encuentra un break o se llega


a la ultima instruccin del switch. Las instrucciones asociadas al
default (el cual es opcional) se ejecutan si no se ha encontrado
ninguna correspondencia.
/* Ejemplo: Imprime un color segun su codigo */
char color;
switch (color) {
case 'a':
case 'A': printf("AMARILLO\n");
break;
case 'r':
case 'R': printf("ROJO\n");
break;
case 'v':
case 'V': printf("VERDE\n");
break;
case 'b':
case 'B': printf("BLANCO\n");
break;
default: printf("CODIGO DESCONOCIDO\n");
}
Se pueden tener un switch formando parte de la secuencia de
instrucciones de otro switch.

Iteracin
Las instrucciones de iteracin (bucles) permiten ejecutar una instruccin o
un conjunto de ellas, mientras se cumpla una determinada condicin. C
contempla tres instrucciones de iteracin: while, do-while y for.

Mayo 2013

54

Introduccin al
Lenguaje de Programacin C

while (exp)
instruccin
+

En el while, la instruccin se ejecuta mientras la expresin sea


verdadera.
/* Ejemplo: Calculo de la media de un vector */
int vector[100], i = 0, media, suma = 0;
while (i < 100)
suma += vector [i++];
media = suma / 100;

do
instruccin
while(exp);
+
-

En el do-while la instruccin se ejecuta mientras la expresin sea


verdadera, a diferencia del while, que analiza la condicin del bucle
al principio, el bucle do-while comprueba la condicin al final. Esto
significa que las instrucciones se ejecuta al menos una vez.

Mayo 2013

55

Introduccin al
Lenguaje de Programacin C

/* Ejemplo: Calculo de la media de un vector */


int vector[100], i, media, suma = 0;
i = 0;
do
suma += vector [i++];
while (i < 100);
media = suma / 100;
Aunque sea una sola instruccin, con frecuencia se colocan entre
llaves { y } por legibilidad del cdigo.

int vector[100];
int main(void){
int i=0, media, suma = 0;
do{
suma += vector [i++];
}while (i < 100);
media = suma / 100;
return 0;
}

for(exp1;exp2;exp3)
instruccin

La instruccin for equivale directamente a lo siguiente:

exp1;
while (exp2) {
instruccin
exp3;
}

Mayo 2013

56

Introduccin al
Lenguaje de Programacin C

Cualquiera de las tres expresiones se pueden omitir, aunque deben


permanecer los ; (puntos y coma), si exp1 y exp3 se omiten los
mismos se desecharan en la expansin ahora si exp2 se omite
entonces se tomara como verdadera permanentemente.
/* Ejemplo: Calculo de la media de un vector */
int v[100], i, media, suma = 0;
for (i = 0; i < 100; i++)
suma += v[i];
media = suma / 100;
Cuando

utilizar

for

while,

si

no

hay

inicializaciones

incrementos el while es ms natural de caso contrario el for es ms


compacto y lo mantiene todo junto y visible, pero al final de cuentas
es una cuestin de preferencia personal.
Dos casos interesantes del for puede ser bucles infinitos (aunque se
puede hacer con otras instrucciones) y los sin cuerpos
Bucle infinito:
for (;;){
...
/* un bucle infinito */
...
}
Sin cuerpos:
for (i=0;i<5;i++); /* bucle sin cuerpo */
Saltos
C tiene cuatro instrucciones de salto incondicional: return, continue, break
y goto. Las instrucciones de return y goto se pueden utilizar en cualquier
parte de una funcin, mientas las instrucciones continue y break se utilizan

Mayo 2013

57

Introduccin al
Lenguaje de Programacin C

junto a instrucciones de iteracin, Adicionalmente ya se estudio el uso del


break en los switch.
return [exp];
Retorna de una funcin, hace que la ejecucin vuelva a punto en
que se realiz la llamada, cuando se acompaa de una expresin,
el valor de la expresin es el valor de vuelta de la funcin. Un return
sin expresin se utiliza para retornar de las funciones tipo void.
Continue;
Solo puede aparecer dentro de una instruccin de iteracin y fuerza
una nueva iteracin (a verificar la condicin) del ciclo ms anidado
que encierra la instruccin.
break ;
Cuando esta dentro de una instruccin de iteracin fuerza la
terminacin inmediata del ciclo ms anidado que encierra la
instruccin, pasando el control a la instruccin siguiente a la
terminada. Como se menciono anteriormente ya se estudio el uso
del break en los switch.
goto etiqueta;
Salta a una etiqueta dentro de la misma funcin, transfirindose el
control a la instruccin etiquetada.
exit(int)
Aunque no es una instruccin de control es una funcin de la
biblioteca estndar que termina la ejecucin del programa cuando
se le llama, el argumento de exit est disponible para proceso de
llamada (se usa 0 para indicar la terminacin normal del programa)

Mayo 2013

58

Introduccin al
Lenguaje de Programacin C

se tienen definido las siguientes macros EXIT_SUCESS y EXIT_FAILURE


como cdigos de vueltas. La funcin exit requiere la inclusin del
archivo de cabecera <stdio.h>
Ejemplo del uso de continue y break en una instruccin de iteracin

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

int main(void) {
int i,p=0;
printf("Antes del for\n");
for(i=0;i<10;i++){
printf("La primera del for\n");
if(++p==1) continue;
if(p==2)break;
printf("La ultima del for\n");
}
printf("Despues del for\n");
return EXIT_SUCCESS;
}

Antes del for


La primera del for
La primera del for
Despues del for

A continuacin se muestra un ejemplo con multiples estructuras de control de


flujo, se destaca el uso del operador , (coma) en el for y la instruccin break en el
while:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i,j;
for(i=0,j=10;i<j;i++,j--)
printf("for: %d - %d\n",i,j);
j=0,i=10;
while(1)

Mayo 2013

59

Introduccin al
Lenguaje de Programacin C

if(i==5)
break;
else
printf("while: %d\n",i--);
do
printf("do-while:%d\n",j);
while(j!=0);
}
/* --- Fin ejemplo --- */

Ahora se destaca el uso de la instruccin continue:


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i=0,j=100,k;
while(i<j){
printf("%d-%d\n",i,j);
i+=5;
j-=5;
if((k=j-i)>50){
printf("%d\n",k);
continue;
}
i+=5;
j-=5;
}
return 0;
}
/* --- Fin ejemplo --- */

Ahora se observa el uso de la instruccin return y la funcin exit


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>

Mayo 2013

60

Introduccin al
Lenguaje de Programacin C

void funcion(int opcion){


switch (opcion) {
case 1:
break;
case 2:
printf("Retornar al medio de la funcion\n");
return;
case 3:
printf("Salir del programa aqui\n");
exit(EXIT_FAILURE);
}
printf("Retornar por final de la funcion\n");
}
void siempre(void){
printf("Por aqui siempre paso\n");
}
int main(void){
atexit(siempre);
funcion(1);
funcion(2);
funcion(3);
printf("por aqui nunca paso\n");
exit(EXIT_SUCCESS);
}
/* --- Fin ejemplo --- */

En el ltimo ejemplo observe que se utiliza la funcin atexit(), revise en el manual


del lenguaje su uso.

Mayo 2013

61

Introduccin al
Lenguaje de Programacin C

Funciones y parmetros
El lenguaje C slo permite funciones, no hay procedimientos. La forma de
declarar las funciones es la siguiente:
<tipo> identificador(lista parmetros formales){
declaraciones
enunciados
}
Donde tipo es el tipo del dato que devuelve la funcin, que si no aparece se
asume siempre del tipo int y nombre es el identificador de la funcin.
Si una funcin acepta argumentos, se debe declara las variables que reciban los
valores de los argumentos, la declaracin de los parmetros sigue al nombre de
la funcin. Los parmetros de una funcin se comportan como cualquier otra
variable local de la funcin.
En C, las listas de parmetros formales y de parmetros reales no tienen por qu
coincidir en nmero, e incluso en tipo, adicionalmente se pueden definir
funciones con parmetros de longitud variable, como es el caso del la funcin
printf().
En los lenguajes de programacin se contempla principalmente dos formas de
pasar parmetros a una funcin, la primera es por valor donde se copia el valor
de un argumento en el parmetro formal de la subrutina, en este caso los
cambios efectuados sobre el parmetro no afectan al argumento. La segunda
forma es un paso por referencia, donde se utiliza la direccin del argumento en el
parmetro y los cambios realizados dentro de la subrutina en los parmetros se
reflejan en los argumentos.
En C, slo existe paso de parmetros por valor excepto los arreglos que pasan por
referencia. Esto significa, en general, que el cdigo de la funcin puede alterar los

Mayo 2013

62

Introduccin al
Lenguaje de Programacin C

argumentos usados en la llamada de la funcin. Se puede crear una llamada


pasando un apuntador al argumento, en lugar de pasar el propio argumento, por
supuesto es necesario declara los parmetros como tipo apuntador.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
void swap1(int x, int y){
int t;
t=x;
x=y;
y=t;
}
void swap2(int *x, int *y){
int t;
t=*x;
*x=*y;
*y=t;
}
int main(int argc,char **argv){
int a=5,b=10;
printf("a:%d b:%d\n",a,b);
swap1(a,b);
printf("a:%d b:%d\n",a,b);
swap2(&a,&b);
printf("a:%d b:%d\n",a,b);
return 0;
}
/* --- Fin ejemplo --- */

Para terminar la ejecucin de una funcin se usa la sentencia return. Su sintaxis es:
return [expresin];
Donde la expresin es el valor que retorna la funcin y debe ser del mismo tipo

Mayo 2013

63

Introduccin al
Lenguaje de Programacin C

que el de la funcin.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
int buscar(int e, int array[], int size){
register int i;
for(i=0;i<size;i++)
if(array[i]==e)
return i;
return -1; // No se encuentra
}
int main(int argc,char **argv){
int a[]={2,5,8,9,10};
printf("Esta en:%d\n", buscar(8,a,5));
return 0;
}
/* --- Fin ejemplo --- */

La forma de invocar a una funcin es similar a otros lenguajes, pero aunque la


funcin no tenga parmetros se deben colocar los parntesis. Por otra parte, es
lcito no realizar ninguna accin con el resultado que devuelve una funcin, pero
en ese caso debiera ponerse un type cast (void) en la llamada.

El uso de void en funciones


Las funciones pueden devolver valores de los tipos bsicos o de los estructurados,
en las funciones que no retornen nada (procedimiento) el tipo devuelto se
declara como void. Uno de los uso de void es declarar explcitamente funciones
que no retornan valores, esto previene su uso en cualquier expresin y puede
ayudar a descubrir errores por un mal uso.

Mayo 2013

64

Introduccin al
Lenguaje de Programacin C

As mismo, cuando no exista ningn parmetro formal, se deben poner


simplemente los dos parntesis ( ) o (void).
void nada(void){
;
}

Prototipos de funciones
En la forma apropiada de escribir programas, todas las funciones deben estar
declaradas antes de ser utilizadas, para lo cual se puede declarar el prototipo de
la funcin antes de invocarla, aunque los prototipos no son obligatorios se
recomienda su uso, ya que permite que el compilador realice comprobaciones
de tipos entre los argumentos utilizados en la llamada (parmetros reales) y en la
definicin de la funcin (parmetros formales), as como del numero de
argumentos.
La forma de escribir el prototipo de una funcin es la siguiente:
<tipo> identificador (<tipo parmetro_1>, <tipo parmetro_N>);
A continuacin se muestra el uso de prototipo de funciones, observe que la
funcin swap() est definida luego de la funcin main().

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
void swap(int *, int *);

// Prototipo de la funcion

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


int a=5,b=10;
printf("a:%d b:%d\n",a,b);

Mayo 2013

65

Introduccin al
Lenguaje de Programacin C

swap(&a,&b);
printf("a:%d b:%d\n",a,b);
return 0;
}
void swap(int *x, int *y){
int t;
t=*x;
*x=*y;
*y=t;
}
/* --- Fin ejemplo --- */

Funciones recursiva
C soporta el llamado recursivo de una funcin, es decir una funcin que se llame
a s misma. La recursin es el proceso de definir algo en trminos de s mismo.
Cuando se llama a una funcin, se asigna espacio en la pila de ejecucin para
los parmetros y las variables locales, el cdigo de la funcin se ejecuta sobre
estas entradas en la pila desde el principio. Adicionalmente en la pila se guarda el
punto donde se reanudar la ejecucin cuando se retorne de la funcin. Es decir
cuando una funcin se llama a s misma, no se crea una copia de ella, solo se
asigna espacio en la pila para los nuevos parmetros y las variables locales y al
retornar de la llamada se tienen en la pila los variables locales y los parmetros
antiguos y se reanuda la ejecucin en el punto inmediato a donde se realizo la
llamada recursiva dentro de la funcin.
Por lo general las soluciones iterativas son ms eficientes que las recursivas, hay
que recordar que en soluciones recursivas se tiene la sobrecarga de las repetidas
llamadas a la funcin, que podran llegar desbordar la pila, como es el caso de
una funcin recursiva descontrolada. La principal ventaja de las funciones
recursivas es que se puede utilizar para crear algoritmos ms claros y sencillos.
Adicionalmente hay problemas que su solucin es naturalmente recursivas y

Mayo 2013

66

Introduccin al
Lenguaje de Programacin C

soluciones iterativas pueden ser difcil de implementar.

El siguiente programa resuelve, de forma recursiva, el clsico problema de las


torres de Hani:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void hanoi(int n,char desde,char hasta,char usando){
if(n==1){
printf("%c --> %c\n",desde,hasta);
return;
}
hanoi(n-1,desde,usando,hasta);
printf("%c --> %c\n",desde,hasta);
hanoi(n-1,usando,hasta,desde);
}
int main(void){
hanoi(3,'A','B','C');
return 0;
}
/* --- Fin ejemplo --- */

Ahora se puede observar usando el valor de retorno de la funcin, para mostrar la


cantidad de movimientos realizados:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int hanoi(int n,char desde,char hasta,char usando){
int m;
if(n==1){
printf("%c --> %c\n",desde,hasta);

Mayo 2013

67

Introduccin al
Lenguaje de Programacin C

return 1;
}
m=hanoi(n-1,desde,usando,hasta);
printf("%c --> %c\n",desde,hasta);
m+=hanoi(n-1,usando,hasta,desde);
return m+1;
}
int main(void){
printf("movimientos:%d\n",hanoi(3,'A','B','C'));
return 0;
}
/* --- Fin ejemplo --- */

A continuacin se muestra el uso de funciones.


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
/* Ejemplo: Bsqueda binaria */
int busqueda_binaria(int elemento,int vector[], int tamano){
int bajo=0,alto=tamano-1,central,valor;
while(bajo<=alto){
central=(alto+bajo)/2;
valor=vector[central];
if(elemento==valor)
return central;
if(elemento < valor)
alto=central-1;
else
bajo=central+1;
}
return -1;
}
int main(void){
int valores[10]={1,5,8,9,10,23,25,30,40,50};
int elemento=12;
printf("Posicin de %d es %d\n",elemento,
busqueda_binaria(elemento,valores,10));
exit(EXIT_SUCCESS);
}

Mayo 2013

68

Introduccin al
Lenguaje de Programacin C

/* --- Fin ejemplo --- */

Otro ejemplo con funciones

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
struct punto{
int x,y;
} p1;
/* funcion minima */
nada(){}
void saludo(void){
printf("Operaciones con puntos\n");
}
void imprime(struct punto p){
printf("punto: %d,%d\n",p.x,p.y);
}
struct punto suma(struct punto p1, struct punto p2){
struct punto t;
t.x = p1.x + p2.x;
t.y = p1.y + p2.y;
return t;
}
int main(int argc,char **argv){
struct punto p1 = {1,2},p2;
saludo();
imprime(p1);
p2=p1;
imprime(p2);
p2=suma(p1,p2);
imprime(p2);
nada();
return 0;
}
/* --- Fin del programa --- */

Mayo 2013

69

Introduccin al
Lenguaje de Programacin C

Funciones inline
C99 aadio la palabra clave inline que se aplica a funciones, precediendo una
funcin la palabra reservada inline se le indica al compilador que optimice la
llamada a esa funcin, eso significa que ha de expandir el cdigo de la funcin
insertndolo en la llamada. Siendo esto una solicitud que pudiera ser ignorada.
Una para utilizar funciones inline es tener cdigo eficiente mientras se mantiene un
enfoque estructurado basado en funciones.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int vector[20]=
{30,35,38,58,14,15,50,27,10,20,12,85,49,65,86,60,25,90,5,16};
void imprimir(int x[],int n){
register int i;
for(i=0;i<n;i++)
printf("%d ",x[i]);
printf("\n");
}
inline void swap(int *x, int *y){
int t;
t=*x;
*x=*y;
*y=t;
}
void ordenarSeleccion(int array[],int size){
register int i,j;
int e;
for(i=0; i<size-1; i++){
e=i;
for(j=i+1; j<size; j++)
if(array[e]>array[j])
e=j;
if(i!=e)
swap(&array[i],&array[e]);
}

Mayo 2013

70

Introduccin al
Lenguaje de Programacin C

}
int main(void){
imprimir(vector,20);
ordenarSeleccion(vector,20);
imprimir(vector,20);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

71

Introduccin al
Lenguaje de Programacin C

Arreglos, Estructuras, Uniones y Enumeraciones


El lenguaje C proporciona varias formas para la creacin de tipos de datos, ya
sean simples o compuestos, a partir de los tipos ya definidos.

Arreglos: Coleccin de variables del mismo tipo que se referencia por un


nombre en comn, y un elemento especifico se accede mediante un
ndice colocando el nombre de arreglo seguido del ndice entre corchetes.
En C los arreglos tiene como 0 como el ndice para su primer elemento, y la
forma de su declaracin la siguiente:
tipo identificado[tamao];
Por ejemplo:
double balance[9];

Acceso al primer elemento:


balance[0] = 123.5;
Los elementos de un arreglo se almacenan de forma contigua,
correspondiendo la direccin ms baja al primer elemento y la direccin
ms alta al ltimo elemento.
Para estimar el nmero de bytes que ocupa la estructura en memoria
basta multiplicar el nmero de elementos por el tamao en bytes del tipo
de dato de cada elemento.
Totalbytes = Tamaobytes(Tipo_Base ) x Tamao del Arreglo

Mayo 2013

72

Introduccin al
Lenguaje de Programacin C

C permite arreglos de ms de una dimensin (multidimensionales), siendo


su forma de declaracin la siguiente:
tipo identificador [tamao1] [tamao2] [tamaoN]
Por ejemplo
int cuad[5][2];

Se puede observar que en la declaracin cada dimensin se coloca en sus


corchetes, de igual forma se procede para acceder a un elemento en
particular. C permite inicializar los arreglos durante la inicializacin con una
lista de elementos separados por coma encerados entre llaves. Se puede
hacer que el compilador calcule la dimensin de los arreglos para
mantener a todos los elementos de la inicializacin, a esto se le denomina
arreglos no delimitados, donde no se especifica la dimensin. Tambin se
puede inicializar un arreglo parcialmente.
char tablero[8][8];
int numero[]={1,2,4,3,9};
int a[10] = {0,1,2,3};
int i,cuad[5][2]={{1,1},{2,4},{3,9},{4,16},{5,25}};
for(i=0;i<5;i++)
printf("el cuadrado de %d es %d\n",cuad[i][0],cuad[i][1]);

En arreglos bidimensionales, se almacenan por filas y columnas (donde el

Mayo 2013

73

Introduccin al
Lenguaje de Programacin C

primer ndice indica las filas y el segundo las columnas) es decir que el
ndice ms a la derecha cambia ms rpido que el de ms a la izquierda
cuando se recorren los elementos en la memoria.
En C89 se deben declarar las dimensiones de los arreglos con dimensiones
constantes, sin embargo C99 permite la declaracin de arreglos locales de
longitud variables.
int vector(int n){ // en C99 arreglos de longitud variable
int i,vector[n];
for(i=0;i<n;i
vector[i]=i;
return i;
}

Estructuras: Agrupacin de miembros diferentes que se referencian bajo un


nico nombre.
Struct datos_persona{
unsigned int codigo;
char nombre[30];
char apellido[30];
char sexo;
};

Los elementos que forman parte de una estructura se denomina miembros


(elementos o campos). La palara struct indica al compilador que se est
declarando un nuevo tipo, para declarar una o varias variables del tipo
aadido se puede hacer de de la siguiente forma:
struct datos_persona persona;

Mayo 2013

74

Introduccin al
Lenguaje de Programacin C

Las estructuras pueden anidarse, por ejemplo


struct alumno{
char carnet[10];
char nombres[20];
char apellidos[20];
char direccion[40];
struct fecha{
int d;
char m[4];
int a;
}nacimiento, ingreso, egreso;
};

O se puede declarar una o ms variables a la vez que se declarar la


estructura, como muestra el ejemplo:
struct datos_persona {
unsigned int codigo;
char nombre[30];
char apellido[30];
char sexo;
} persona;
O si solo se necesitan las variables de la estructura, no se requiere el nombre
de la estructura:
struct {
unsigned int codigo;
char nombre[30];
char apellido[30];
char sexo;
} persona;
Las nicas operaciones permitidas sobre una estructura son asignarla, tomar
su direccin con &, tener acceso a sus miembros, pasarla como
argumentos a funciones y tambin regresarlas de funciones. Las estructuras
no se pueden comparar. Las estructuras se pueden inicializar con una lista
de variables constantes y una estructura automtica tambin se puede
inicializar con una asignacin.

Mayo 2013

75

Introduccin al
Lenguaje de Programacin C

El acceso a los miembros de una estructura se realizar con el operador .


(punto) por ejemplo:
persona.sexo = F;

A travs de una nica asignacin, se puede asignar el contenido de una


estructura a otra, no es necesaria la asignacin de cada miembro por
separado.
Cuando se pasa una estructura a una funcin como un parmetro
realmente se pasa por valor la estructura completa.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
struct punto{
int x,y;
} p1;
void imprime(struct punto p){
printf("punto: %d,%d\n",p.x,p.y);
}
struct punto suma(struct punto p1, struct punto p2){
struct punto t=p2;
t.x += p1.x;
t.y += p1.y;
return t;
}
int main(int argc,char **argv){
struct punto p1 = {1,2},p2;
imprime(p1);
p2=p1;
imprime(p2);
p2=suma(p1,p2);
imprime(p2);
return 0;
}
/* --- Fin del programa --- */

Mayo 2013

76

Introduccin al
Lenguaje de Programacin C

Las estructuras pueden ser inicializadas


struct punto{
float x;
float y;
} p1={1.0, 1.0}, p2={-1.0, -1.0};
Los arreglos de estructura se pueden inicializar de la forma habitual,
struct items{
char descripcion[20];
int cantidad;
float costoUnitario;
} almacen[] = {{"clavos",10,0.5},
{"tuercas",15,1.0},
{"tornillos",20,1.5}};

Uniones: Permite que una misma parte de la memoria sea definida como
dos o ms tipos.
Union numero{
int entero;
float real;
}

Cuando una variable se declara como una union el compilador reserva


espacio para el mayor de los miembros. Pos su naturaleza las uniones
proporciona un mecanismo para interpretar una secuencia de bits de
diferentes formas. Y su declaracin y uso es similar a las estructuras.

Campo Bits: tipo especial de estructura o unin que permite el fcil acceso
a bits individuales. Se declaran de la siguiente forma:
tipo nombre: longitud;
Y no es necesario nombrarlos, por ejemplo:

Mayo 2013

77

Introduccin al
Lenguaje de Programacin C

Struct estado{
unsigned: 4;
unsigned cts:1;
unsigned drs:1;
}
Enumeraciones: Una lista de constantes enteros con nombres.
La declaracin tendr la siguiente forma:
enum nombre { lista_de_enumeracion } ;
Ejemplo:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
enum dias{Domingo, Lunes, Martes, Miercoles, Jueves, Viernes,
Sabado};
int main(int argc,char **argv){
enum dias dia;
for(dia=Domingo;dia<=Sabado;dia++){
printf("%d\n",dia);
}
return 0;
}
/* --- Fin del programa --- */

En una enumeracin cada una de los elementos se corresponde con un


valor entero, donde el primero se corresponde con el cero y los siguientes
se incrementan en uno sucesivamente, aunque se pueden definir otros
valores utilizando un inicializador (el signo de igualdad seguido de un valor
entero) a los elementos que siguen a uno inicializado se les hace
corresponder el valor previo incrementado en uno sucesivamente.
Como los elementos se corresponden con constantes enteras se puede

Mayo 2013

78

Introduccin al
Lenguaje de Programacin C

usarse en cualquier expresin entera.

Ejemplo usando estructuras y uniones:


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
typedef unsigned int PALABRA;
typedef struct{
unsigned a:1;
unsigned b:1;
unsigned :4;
unsigned c:1;
unsigned d:1;
} SBITS;
typedef union{
PALABRA palabra;
SBITS bits;
}AMBOS;
int main(void){
AMBOS a;
a.palabra=0;
printf("Sizeof Palabra%d\n",sizeof(PALABRA));
printf("Sizeof SBITS%d\n",sizeof(SBITS));
printf("Sizeof UNION%d\n",sizeof(AMBOS));
printf("%d\n",a.palabra);
a.bits.c=1;
printf("%d\n",a.palabra);
return 0;
}
/* --- Fin ejemplo --- */

Ahora un ejemplo con arreglos:


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/

Mayo 2013

79

Introduccin al
Lenguaje de Programacin C

#include <stdio.h>
int buscar(int e,int a[],int t){
register int i;
for(i=0;i<t;i++)
if(a[i]==e)
return i;
return -1;
}
int main(void){
int a[]={2,3,6,8,10,12,23,15,22,1,9,7};
printf("Buscar 12:%d\n",buscar(12,a,12));
printf("Buscar 25:%d\n",buscar(25,a,12));
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

80

Introduccin al
Lenguaje de Programacin C

Apuntadores
Los apuntadores son una de las caractersticas ms tiles y a la vez ms peligrosas
de que dispone el lenguaje C. En C se permite declarar una variable que
contiene la direccin de otra variable, o sea, un apuntador. Cuando se declara
un apuntador ste contiene una direccin arbitraria, si leemos a dnde apunta
nos dar un valor indefinido y si se escribe en tal direccin estamos variando el
contenido de una posicin de memoria que no conocemos por lo que podemos
hacer que el sistema tenga comportamientos no deseados, por lo que antes de
hacer uso de un puntero debemos asignarle una direccin de memoria en
nuestro espacio de trabajo.
La forma de declarar un apuntador es la siguiente:
tipo *nombre;
Por ejemplo la declaracin:
int i, *p=&i;
Se muestra grficamente:

El tipo indica al tipo de datos a los que apuntar el apuntador, pero como efecto
de la declaracin se reservar espacio en memoria para guardar un apuntador,
no para el tipo de datos al que apunta es decir la declaracin de un apuntador
no lleva asociada la reserva de espacio para el tipo de datos apuntado.
Existe un carcter especial que se usa como prefijo y aplicado a las variables
indica la direccin de memoria que ocupa la variable, no el contenido (valor).
Este smbolo es &. Adems existe otro prefijo, *, que aplicado a una variable de
tipo puntero indica el contenido de la direccin a la que apunta dicho
apuntador. A estos dos smbolos se les llama direccin e indireccin (contenido)

Mayo 2013

81

Introduccin al
Lenguaje de Programacin C

respectivamente.

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i,*ip;
i=0;
ip=&i;
*ip=5;
printf("i:%d\n",i);
return 0;
}
/* --- Fin ejemplo --- */

Aritmtica de apuntadores
A los apuntadores se les puede aadir o restar una cierta cantidad entera.
Admiten comparaciones e incrementos y decrementos. Cuando un apuntador es
incrementado en uno pasa a apuntar al siguiente elemento del arreglo al que
apuntaba, no al siguiente byte, es decir, se incrementa en el nmero de bytes
que ocupa el tipo al que apunta. Si p es un apuntador a un elemento de un
arreglo p++ incrementa el apuntador para apuntar al siguiente elemento (de
forma similar funciona p-- pero apuntado al elemento anterior). No solo esta
limitado a funciones auto incremento o auto decremento

por ejemplo la

expresin p+=i ( o p = p + i) lo incrementa para apuntar i elementos adelante.


Adems de la suma y resta de un apuntador y un entero, solo se puede hacer
una operacin ms restar un apuntador con otro a fin de obtener el numero de
objeto del tipo base que separan a ambos apuntadores, es decir calcular la
distancia entre ellos. Todas las dems operaciones esta prohibidas.

Mayo 2013

82

Introduccin al
Lenguaje de Programacin C

Se pueden comparar apuntadores que apunte a miembros del mismo arreglo, en


una expresin relacional, por ejemplo: p < q. y cualquier apuntador puede ser
comprado por su igualdad o desigualdad con cero o NULL, por ejemplo p!=NULL
o !p
Un buen ejemplo para aritmtica de apuntadores de la funcin que calcula la
longitud de una cadena de caracteres (string).

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <malloc.h>
char *ms = "HOLA MUNDO";
int mystrlen(const char *s){
const char *p = s;
while(*p)
p++;
return p-s;
}
int main(void){
printf("ms:%s\n",ms);
printf("Longitud ms:%d\n",mystrlen(ms));
return 0;
}
/* --- Fin ejemplo --- */

Apuntadores a apuntadores
Se puede hacer un apuntador que apunte a otro apuntador que apunte a una
variable. Esta situacin se denomina apuntador de apuntador o indireccin
mltiples.

Esta situacin puede llevarse a la extensin que se desee por ejemplo

un apuntador a un apuntador a un apuntador, pero son pocos los casos que lo


requieran ms all de un apuntador a un apuntador, La indireccin mltiple en

Mayo 2013

83

Introduccin al
Lenguaje de Programacin C

exceso puede resultar difcil de seguir y puede ser propensa a errores.


Por ejemplo la siguiente declaracin:
int i=10 *p=&i, *pp=&p;
Se representa grficamente:

Como se puede observar en la figura en el caso de un apuntador a un


apuntador, el primer apuntador contiene la direccin del segundo apuntador,
que apunta a la variable que contiene el valor deseado.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(int argc,char **argv){
int i=5,j=10,*p=&i,**pp=&p;
printf("valor de *p:%d\n", *p);
printf("valor de **pp:%d\n", **pp);
p=&j; /* No se cambia pp pero ... */
printf("valor de **pp:%d\n", **pp);
return 0;
}
/* --- Fin del programa --- */

Un arreglo de apuntadores es un caso particular de apuntadores a apuntadores.

Relacin entre apuntadores y arreglos


Los apuntadores y los arreglos en C estn relacionados ntimamente y puede ser
utilizado casi en forma indistinta. Un nombre de arreglo puede considerarse como
un apuntador, los apuntadores pueden utilizarse para realizar cualquier operacin

Mayo 2013

84

Introduccin al
Lenguaje de Programacin C

que involucre arreglos.


Por ejemplo si se declara un arreglo de enteros int ia[5]; y un apuntador a
entero int *iap; Dado que el nombre del arreglo si elemento es un apuntador
al primer elemento se hacer al apuntador igual a la direccin del primer elemento
iap=ia; (o ms extrao iap=&ia[0];) alternativamente el elemento ia[3]
puede ser referenciado como *(ia+3)
Existe una diferencia entre el nombre de un arreglo y un apuntador, un apuntador
es una variable, por eso iap++ es legal. Pero el nombre de un arreglo no es una
variable por lo que ia++ , por ejemplo, es ilegal.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(int argc,char *argv[]){
int *iap, ia[5]={0,1,2,3,4};
iap=ia;
printf("ia[3]:%d\n",ia[3]);
printf("*(iap+3):%d\n",*(iap+3));
printf("*(3+iap):%d\n",*(3+ia));
printf("3[ia]:%d\n",3[ia]);
return 0;
}
/* --- Fin ejemplo --- */

Aunque los arreglos y los apuntadores estn ntimamente relacionados, hay que
estar muy claro que existe una diferencia importante entre estas dos
declaraciones:
char msg_a[] = HOLA MUNDO
// Arreglo
char *msg_p = HOLA MUNDO // Apuntador
Veamos:

Mayo 2013

85

Introduccin al
Lenguaje de Programacin C

msg_a:

\0

msg_p:
H

\0

Recordemos que en la declaracin de un apuntador, se reservar espacio en


memoria para guardar un apuntador, en este caso en particular, el apuntador se
inicializa con el inicio de la cadena de caracteres HOLA MUNDO.
El uso de apuntadores y de la aritmtica de apuntadores puede dar como
resultados programas muy eficiente, hay que tener en cuenta la legibilidad del
cdigo.
Un NO buen ejemplo:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#define MAX 12
int a[MAX]={11,7,6,5,4,3,1,0},
b[MAX]={10,9,8,4,3,2,0},
c[2*MAX-1]={0};
void imprime(const int *x){
for(;*x;x++)
printf("%d ",*x);
printf("\n");
}
void merge(const int *f1,const int *f2,int *d){
while(*d++=*f1>*f2?*f1++:*f2++);
}
int main(void){

Mayo 2013

86

Introduccin al
Lenguaje de Programacin C

imprime(a);
imprime(b);
merge(b,a,c);
imprime(c);
return 0;
}
/* --- Fin ejemplo --- */

Puede resultar difcil de leer la funcin merge y si se detalla se puede observar


que no es del todo eficiente.
El siguiente ejemplo se evidencia la diferencian de usar arreglos y apuntadores,
en la manipulacin de cadenas de caracteres (string), en nuestro caso en
particular la copia de una cadena de caracteres.
Empezamos implementado la funcin mystrcpy con arreglos.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
char A[] = "HOLA MUNDO",B[12];
void mystrcpy(char d[],char f[]){
register int i;
i=0;
while((d[i]=f[i])!='\0')
i++;
}
int main(void){
printf("A:%s\n",A);
mystrcpy(B,A);
printf("B:%s\n",B);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

87

Introduccin al
Lenguaje de Programacin C

Ahora con apuntadores, razone las ventajas de esta aproximacin.


void mystrcpy(char *d,const char *f){
while((*d=*f)!='\0'){
d++;
f++;
}
}

Ahora un poco ms eficiente, utilizando apuntadores.


void mystrcpy(char *d,const char *f){
while(*d++=*f++);
}

Aunque nos pueda parecer poco legible al principio, es importante


acostumbrase a este estilo de programacin puesto que el que se
consigue con frecuencia en aplicaciones y ejemplos.

Como utilizar el calificador const con apuntadores


El calificador const permite informarle al compilador que el valor de una variable
en particular no deber ser modificado. Existen cuatro formas de declara o pasar
un apuntador a una funcin:
Un apuntador no constante a datos no constantes
char *s
Un apuntador no constante a datos constantes
const char *s
Un apuntador constante a datos no constantes
int * const ip
o
int i;
int * const ip=&i;

Mayo 2013

88

Introduccin al
Lenguaje de Programacin C

Un apuntador constante a datos constantes


const int * const ip
O
int i=5;
const int * const ip=&i;
Ejemplo intento de modificacin de datos a travs de un apuntador no constante
a datos constantes

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(void){
int i=5;
const int *ip=&i;
*ip=2;
printf("%d",*ip);
return 0;

/* operacion invalida */

}
/* --- Fin ejemplo --- */

Arreglos de apuntadores
Al igual que de cualquier otro tipo de dato se permite declarar un array de
punteros. La forma de hacerlo es:
tipo *nombre[expresion1][expresion2];

int

Mayo 2013

*iap[5];

89

Introduccin al
Lenguaje de Programacin C

float *afp[];
void (*funciones[3])()={funcion1,funcion2,funcion3};
A continuacin se muestra el uso de arreglos de apuntadores:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void print_error(const int num){
static char *err[]={
"Error numero cero",
"Error numero uno",
"Error numero dos",
"Error numero tres"
};
printf("Error (%d):%s\n",num,err[num]);
}
int main(void){
print_error(2);
return 0;
}
/* --- Fin ejemplo --- */

Arreglo de apuntadores vs. arreglos multidimensionales


Analicemos el siguiente programa
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
char *cpa[]={"Esta"," es"," una"," Prueba"};
char cba[][8]={"Esta"," es"," una"," Prueba"};
int main(void){
printf("sizeof(char *cpa[]):%d\n",sizeof(cpa));
printf("sizeof(char cba[][8]):%d\n",sizeof(cba));

Mayo 2013

90

Introduccin al
Lenguaje de Programacin C

printf("por la dudas %c es %c\n",cpa[3][1],cba[3][1]);


printf("*cpa[2]:%s\n",cpa[2]);
printf("cba[2]:%s\n",cba[2]);
return 0;
}
/* --- Fin ejemplo --- */

Para cba , al ser un arreglo bidimensional, se reserva 4x8 sizeof(char) ahora para
cpa, al ser un arreglo de apuntadores a caracteres, se reserva 4xsizeof(char *). En
el caso en que cpa apunte a elementos de 8 sizeof(char) entonces se tiene 4x8x
sizeof(char) + 4xsizeof(char *). Ahora la ventaja del arreglo de apuntadores es que
los reglones pueden ser de longitudes diferentes.

Apuntadores a estructuras
Existe una pequea variacin a la hora de acceder a una estructura mediante un
apuntador, por ejemplo, (*p).miembro se puede escribir como p->miembro.

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>

Mayo 2013

91

Introduccin al
Lenguaje de Programacin C

struct campos{
char campo1;
int campo2;
int campo3[4];
} e, *ep, ea[4];
int main(void){
e.campo1='a';
e.campo2=25;
ep=&e;
printf("campo1:%c\n",(*ep).campo1);
printf("campo2:%d\n",ep->campo2);
ea[2].campo3[1]=123;
printf("ea[2].campo3[1]:%d\n",ea[2].campo3[1]);
return 0;
}
/* --- Fin ejemplo --- */

Estructuras autoreferenciadas
Una estructura no puede contener un miembro de tipo incompleto (que no est
declarado), por lo tanto es imposible declarar estructuras (o uniones) que
contengan una instancia de ellas mismas. Sin embargo adems de dar nombre a
una estructura, los rtulos permiten la definicin de estructuras autoreferenciadas,
es decir estructura que contienen un apuntador (o apuntadores) a una instancia
de ella misma. Debido a que se pueden ser declarados apuntadores a tipos
incompletos.
Como ejemplo de estructuras autoreferenciadas se tienen las estructuras
dinmicas, tales como las lista simplemente o doblemente enlazadas, arboles
binarios, etc.
A continuacin se muestra la declaracin de un nodo de un rbol binario
struct abNodo{
char clave[20];
int cuenta;
struct abNodo *izq;
struct abNodo *der;
};

Mayo 2013

92

Introduccin al
Lenguaje de Programacin C

Como se puede observar en la estructura abNodo los campos izq y der, son
apuntadores a una estructura abNodo, en este caso apuntadores a los nodos hijo
izquierdo y derecho.

Pase de apuntadores a funciones


El lenguaje C slo admite paso de parmetros por valor, pero tiene una forma de
simular un paso por referencia (variable), pasando un apuntador que es la
direccin donde estn los datos (p. ej. &v). En realidad se pasa un valor que es
una direccin de una variable.

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void intercambia1(int x,int y){
int z;
z=x;
x=y;
y=z;
}
void intercambia2(int *x,int *y){
int z;
z=*x;
*x=*y;
*y=z;
}
int main(void){
int a=2,b=3;
printf("a:%d b:%d\n",a,b);
intercambia1(a,b);
printf("a:%d b:%d\n",a,b);
intercambia2(&a,&b);
printf("a:%d b:%d\n",a,b);
return 0;

Mayo 2013

93

Introduccin al
Lenguaje de Programacin C

}
/* --- Fin ejemplo --- */

Apuntadores a funciones
Es posible crear apuntadores que apunten a funciones, en lugar de datos los
apuntadores a funciones apuntan a cdigo ejecutable. Los apuntadores a
funcin permiten pasar a una funcin como argumento a otra funcin.
Un ejemplo de arreglo de funciones:
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void funcion1(){
printf("Funcion 1\n");
}
void funcion2(){
printf("Funcion 2\n");
}
void funcion3(){
printf("Funcion 3\n");
}
int main(void){
void (*funciones[3])()={funcion1,funcion2,funcion3};
int opcion;
printf("Opcion (1-3) => ");
scanf("%d",&opcion);
if(opcion>=1 && opcion <=3)
(*funciones[opcion-1])();
else
printf("Error en opcion\n");
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

94

Introduccin al
Lenguaje de Programacin C

Paso de una funcin como argumento a otra funcin:


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
void funcion1(){
printf("Funcion 1\n");
}
void funcion2(){
printf("Funcion 2\n");
}
void funcion3(){
printf("Funcion 3\n");
}
void llamar_opciones(void (*funcion)()){
printf("Llamar opciones:");
(*funcion)();
}
int main(void){
void (*funciones[3])()={funcion1,funcion2,funcion3};
int opcion;
printf("Opcion (1-3) => ");
scanf("%d",&opcion);
if(opcion>=1 && opcion <=3)
llamar_opciones(funciones[opcion-1]);
else
printf("Error en opcion\n");
return 0;
}
/* --- Fin ejemplo --- */

Apuntadores genricos
Un apuntador void * se denomina un apuntador genrico, y se utiliza para
especificar un apuntador cuya base se desconoce. En C se puede asignar un
apuntador void * a cualquier otro tipo de apuntador y viceversa .

Mayo 2013

95

Introduccin al
Lenguaje de Programacin C

void* permite especificar a una funcin un parmetro que pueda recibir cualquier
tipo de apuntador como argumento. Tambin se utiliza para referirse a la
memoria en bruto (caso de la funcin malloc) cuando se desconoce el
significado de la memoria.

Conversin de apuntadores
Se puede convertir un tipo de apuntador en otro tipo de apuntador, las dos
categoras son las que involucran apuntadores void * y las que no.
Apuntadores y los enteros no son intercambiables, siendo el cero la nica
excepcin (puede ser asignada y se puede comparar) se emplea la constante
simblica NULL en lugar del cero con frecuencia.

Mayo 2013

96

Introduccin al
Lenguaje de Programacin C

La biblioteca estndar
En el lenguaje C toda la entrada y salida de un programa se realiza a travs de
funciones definidas en Bibliotecas. Tambin se encuentran definidas en
bibliotecas otros tipos de funciones. Dichas bibliotecas, o la mayora, son estndar
(las funciones en ellas definidas tienen nombres estndar) lo que facilita la
portabilidad de los programas. Al inicio de cada archivo se debe indicar las
declaraciones de las bibliotecas que se utilizarn. Esto se realiza utilizando la
directiva #include, cuya sintaxis es:
#include nombre_archivo
Donde nombre_archivo es el archivo de encabezado, donde se realizan las
definiciones de la bibliotecas, se coloca entre signos de menor y mayor
(<nombre_archivo>) o entre comillas dobles ("nombre_archivo") segn el lugar en
que haya que buscar el archivo ya sea en los directorios asignados por defecto a
los archivos incluye o en el actual.
Estos archivos de definiciones suelen tener la extensin .h (de header, cabeceras)
y contienen definiciones necesarias para la utilizacin de las funciones contenidas
en la biblioteca.
Por ejemplo:
#include <stdio.h>
Incluye la cabecera para usar la biblioteca de entrada/salida desde el directorio
estndar
#include "stdio.h"
Igual al anterior pero las busca en el directorio actual
#include "c:\proyecto\colas.h"
Incluye el archivo colas.h del directorio proyecto

Archivos de encabezados de algunas libreras estndares importantes en ANSI C:

Mayo 2013

97

Introduccin al
Lenguaje de Programacin C

conio.h

Soporte para I/O por consola y puertos.

ctype.h

Manejo de caracteres.

errno.h

Informes de error.

float.h

Valores de flotantes dependiente de la implementacin.

io.h

Entrada y salida a bajo nivel.

malloc.h

Soporte para las funciones para obtener y liberar memoria.

math.h

Conjunto de funciones matemticas.

setjmp.h

Soporte para saltos no locales

signal.h

Soporte para el manejo de seales.

stdarg

Soporte para lista de argumentos de longitud variable.

stdio.h

Entrada y salida estndar.

stdlib.h

Conjunto de funciones estndar, p.e. conversin de tipos.

string.h

Funciones de manejo de cadenas.

time.h

soporte para las funciones de tiempo del sistema

Adicionalmente dependiendo del Sistema de Operacin se puede encontrar


biblioteca para el llamado a las primitivas del Sistema de Operacin, en el caso
de UNIX, se tiene entre otras:

signal.h

para el manejo de seales del sistema

sys/sem.h

para el manejo de semforos

sys/shm.h

manipulacin de memoria compartida

sys/socket

manejo de manejo de socket

A continuacin se muestra el uso de biblioteca <setjmp.h> para saltos no locales


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <setjmp.h>
jmp_buf env;

Mayo 2013

98

Introduccin al
Lenguaje de Programacin C

void funcion4(void){
printf("Primera de Funcion4\n");
longjmp(env,1);
printf("Segunda de Funcion4\n");
}
void funcion3(void){
printf("Primera de Funcion3\n");
funcion4();
printf("Segunda de Funcion3\n");
}
void funcion2(void){
printf("Primera de Funcion2\n");
funcion3();
printf("Segunda de Funcion3\n");
}
void funcion1(void){
printf("Primera de Funcion1\n");
funcion2();
printf("Segunda de Funcion1\n");
}
int main(void){
if(setjmp(env)==0){
printf("Ahora vamos a llamar las funciones\n");
funcion1();
}
else
printf("Regresamos con \"un salto no local\"\n");
printf("Ahora si salimos\n");
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

99

Introduccin al
Lenguaje de Programacin C

Entrada y Salida
Los principales archivos estndar definidos en toda aplicacin en C son:

stdin (entrada estndar, asociado al teclado)

stdout (salida estndar, asociado a la pantalla)

stderr (error estndar, asociado a la pantalla)

Las principales funciones de entrada y salida son:

putchar(char c) Funcin de salida de carcter. Imprime el carcter c por


la salida estndar.

char getchar(void) Entrada estndar de carcter. Obtiene un carcter de


la entrada estndar y este es el valor que devuelve la funcin.

int printf(const char *format, ...) Imprime por la salida estndar una
secuencia de caracteres cuya estructura est definida en la string format.
Se permite dar salida a cualquier tipo de dato predefinido. La string format
tiene la estructura de una string normal pero admite adems caracteres de
conversin (%) para indicar qu tipo de dato se ha de imprimir.
La estructura de una cadena de formato es:
%[flags][.width][.prec][F|N|h|l]type
donde type es un caracter de conversin. El campo flag afecta al tipo de
justificacin; width a la anchura utilizada para imprimir; .prec a la precisin
a la hora de escribir nmeros en coma flotante. El ltimo campo opcional
afecta a la interpretacin del argumento.

%c Carcter

%d Entero decimal

%e Flotante se representa con exponente

%f Flotante se representa sin exponente

%g Menor entre %e y %f

%o Entero octal, sin el cero inicial

%u Entero decimal sin signo

Mayo 2013

100

Introduccin al
Lenguaje de Programacin C

%x Entero representado en hexa sin 0x

%s Strings (cadenas)

int scanf(const char *format, ...) Es el equivalente a printf para la entrada


estndar de datos de forma estructurada. En la cadena de formato se
pueden poner todos los caracteres de conversin (%) de la tabla anterior.
Adems admite %[cadena], donde se acepta cualquier cadena formada
por elementos pertenecientes a cadena, o si la cadena comienza con '^',
los no pertenecientes y %*c carcter de supresin de asignacin.

FILE *fopen(const char *filename,const char *mode) Abre un archivo en alto


nivel. filename es el nombre del fichero y mode indica el modo de apertura
del fichero. Retorna un puntero al descriptor del fichero (FILE).

"r" Abrir un archivo existente solo para lectura

"w" Abrir un archivo solo para escritura

"a" Abrir un archivo para aadir. Si no existe se crea uno

"r+" Abrir un archivo existente para lectura y escritura

"w+" Abrir un archivo nuevo para lectura y escritura

"a+" Abrir un archivo nuevo para leer y aadir

int fclose(FILE *fp) Cierra un archivo cuyo puntero al descriptor es fp.

int fprintf(FILE *fp,const char *format, ...) Escribe en el archivo descrito por fp
datos con el formato indicado por format.

int fscanf(FILE *fp,const char *format, ...) Lee del archivo descrito por fp.
Tanto esta llamada como la anterior son las equivalentes de printf y scanf
que operan sobre ficheros.

Mayo 2013

101

Introduccin al
Lenguaje de Programacin C

Archivos
Almacenar datos en memoria principal, podra ser temporal al terminal la
ejecucin del programa los datos se perderan. Una forma de conservarlos
permanentemente es haciendo el uso de archivos, lo cual no solo nos dara la
posibilidad de almacenamiento permanente sino la capacidad de almacenar
grandes cantidades de datos. Normalmente asociamos los archivos a dispositivos
de almacenamiento secundario, especialmente los discos. Entonces, un archivo
se puede ver como una secuencia de bytes sin formato almacenados en un
dispositivo que y que puede ser tratado como una unidad lgica. La forma en
que estos bytes son organizados dentro del archivo (formato) pueden ser muy
variados y a depender de

los programas al leerlo de interpretarlos y darle

significado.
La gestin de los archivos es realizada por el sistema de operacin, el cual provee
de un conjunto de primitivas para su manipulacin, El Sistema de Operacin
proporciona servicios a travs de un conjuntos de llamadas al sistema, que son
funciones dentro del sistema que pueden ser invocadas por los programas de
usuarios.
En Unix/Linux el sistema de archivo esta organizado de forma jerrquica con un
nodo principal conocido como root,

/. Cada nodo de la jerarqua es un

directorio y puede a su vez contener otros directorios y archivos. Los archivos


tienen ciertos atributos, tales como su nombre, su tamao, su dueo, permisos,
etc.
Los lenguajes de programacin, por lo general, proveen los tipos e instrucciones
necesarios para la manipulacin de archivos. Recordemos que C no posee
instrucciones para entrada y salida, pero para estos fines existen bibliotecas
estndares de E/S.

Mayo 2013

102

Introduccin al
Lenguaje de Programacin C

Entre las operaciones bsicas sobre archivos se tiene las de abrir y cerrar un
archivo, la de llevar o leer un byte o un conjunto de ellos (bloque, lnea o registro)
a un rea del programa (buffer o algn tipo de almacenamiento temporal) de un
tamao idntico o mayor de la cantidad de bytes ledos.

El sistema de

Operacin facilita la lectura en el orden en que aparecen los bytes o los bloques
dentro del archivo, de forma anloga se llevar o escribir un rea del programa a
un archivo, al escribir en un archivo se colocan en posicin inmediata siguiente al
byte o los bytes colocados previamente.
Adicionalmente existe una instruccin, funcin o marca que nos indican que se
ha alcanzado el final del archivo o eof (end of file).
Como se menciono previamente pueden existir muchos tipos de archivos, una
forma de organizar la informacin en un archivo puede ser haciendo uso de un
registro, es decir un grupo de campos relacionados, entonces se puede ver el
archivo como un conjunto de registros, para facilitar su recuperacin se podra
seleccionar un campo del registro, o una combinacin de ellos, como una clave
lo cual lo identificara de forma nica al registro. Por ejemplo en el caso de
registro de una persona su nmero de cedula. Teniendo en cuenta esto los
archivos se podran organizar de diversas formas, la ms comn se conoce como
secuencial, donde los registros se organizar de forma consecutiva, posiblemente
ordenado por algn criterio, para leer un archivo secuencial se comienza por el
principio y se lee un registro a la vez hasta llegar al registro deseado. Esta
organizacin suele ser til en procesamiento por lotes donde se procesan todos
los registros y no necesariamente todos los registros tienen el mismo tamao, lo
que puede complicar la modificacin de un registro. Para realizar las operaciones
de actualizacin de los registros, usualmente se vuelve a escribir la totalidad del
archivo.

Mayo 2013

103

Introduccin al
Lenguaje de Programacin C

Otra forma de llegar al registro deseado utilizar archivos de acceso directo que
explotan la capacidad de los discos para acceder directamente a cualquier
rea o bloque dada una direccin o desplazamiento, es decir se pueden tratar
de forma anloga a un arreglo. En este tipo de organizacin se requiere una
forma de asociar el contenido de un registro con su posicin, y los registros suelen
ser todos del mismo tamao. Al tener los registros la misma longitud los datos
pueden ser actualizados sin necesidad de reescribir la totalidad del archivo

Adicionalmente pueden existir otros tipos de organizaciones tales como las


indexadas que escapan del alcance de este curso.

Manipulacin de archivos en C
En C los archivos se ven como un flujo secuencial de bytes, que terminan con
marcador de fin de archivo. Cuando se abre un archivo se le asocia un flujo que
no es ms que una estructura de tipo FILE. Al empezar la ejecucin de un
programa se abren automticamente tres archivos y sus flujos correspondientes,
la entrada estndar (stdin), la salida estndar (stdout) y el error estndar (stderr).
Normalmente stdin est conectado al teclado y stdout y stderr se conectan a la

Mayo 2013

104

Introduccin al
Lenguaje de Programacin C

pantalla, pero stdin y stdout pueden ser redireccionados a archivos o a tuberas


(pipes)
Los flujos proporcionan canales de comunicacin entre archivos y los programas.
Al abrir un archivo se retorna un apuntador a una estructura FILE, definida en
<stdio.h> que contiene la informacin requerida para procesar el archivo, tales
como: si el archivo es de lectura o de escritura, buffer, la posicin actual, si se ha
llegado al fin del archivo o si ha ocurrido algn error.
Antes de que un archivo pueda ser ledo o escrito tiene que ser abierto, para lo
cual se debe indicar el nombre del archivo y el modo de apertura, algunos
sistemas distinguen entre archivos de texto y binario, C no impone una estructura
a un archivo por lo que no existe el concepto de registro de archivo.
La biblioteca estndar proporcionan muchas funciones para la manipulacin de
archivos, tales como fopen para abrir un archivo, fclose para cerrarlo, feof para
determinar si se ha alcanzado el final de archivo, fgetc y getc que leen un
carcter, fputc y putc que escribe un carcter a un archivo, se tiene las funciones
fgets y fputs que pueden ser utilizadas para leer una lnea y escribir una lnea a un
archivo y las funciones fprintf y fscanf similares a printf y scanf pero operando
sobre archivos.
Adicionalmente se tienen funciones tales como: fread que transfiere una cantidad
de byte desde la posicin actual del archivo a una localidad de memoria del
programa, fwrite que transfiere una cantidad de bytes desde una localidad del
programa a un archivo. Con ambas funciones normalmente se leen y se escriben
estructuras a la vez, rara veces se manipulan un campo solamente.
Entre otras funciones no menos importante se tiene fseek fija la posicin actual, es
decir una escritura o lectura posterior tendr a acceso a datos que principian en
la nueva posicin y fflush que hace el buffer del archivo se escriba fsicamente en
el archivo.

Mayo 2013

105

Introduccin al
Lenguaje de Programacin C

Ahora estamos en capacidad de escribir nuestro primer programa en C para con


archivos.

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
FILE *af, *ad;
int c;
if(argc != 3){
fprintf(stderr, "Error en argumentos\n");
exit(EXIT_FAILURE);
}
if((af=fopen(argv[1],"r"))==NULL){
fprintf(stderr, "No se puede abrir %s\n",argv[1]);
exit(EXIT_FAILURE);
}
if((ad=fopen(argv[2],"w"))==NULL){
fprintf(stderr, "No se puede abrir %s\n",argv[2]);
exit(EXIT_FAILURE);
}
while((c=getc(af))!=EOF)
putc(c,ad);
fclose(af);
fclose(ad);
printf("%s copiado en %s\n", argv[1], argv[2]);
exit(EXIT_SUCCESS);
}
/* fin del ejemplo */

Mayo 2013

106

Introduccin al
Lenguaje de Programacin C

Memoria Dinmica
Aunque

el

lenguaje

NO

define

ninguna

facilidad

para

asignacin de

almacenamiento que no sea definicin esttica o automtica (usando la pila) no


emplea el head y no define mecanismo de recoleccin de basura, la biblioteca
estndar facilita un sistema de gestin dinmica de memoria (utilizando el
montn) cuyo ncleo est compuesto por las funciones malloc() y free(). Estas
funciones trabajan junta para establecer y gestionar la memoria disponible. La
funcin malloc asigna memoria y la funcin free la libera.
Cualquier programa que utiliza las funciones malloc y free debe incluir el archivo
de cabecera <stdlib.h>. Los prototipos de ambas funciones son:
void *malloc(size_t numero_de_bytes)
Donde el nmero de bytes es la cantidad de memoria que se requiere y
malloc retorna un void * que se asignar a cualquier tipo de apuntador. Si
hay un fallo durante la asignacin malloc retorna nulo (NULL).
La funcin free en la complementaria a malloc ya que devuelve al sistema
la memoria previamente asignadavoid free(void *p)
Ahora p es apuntador previamente asignado. Es muy importante no llamar
nuca a free con un argumento no valido, se daara el sistema de
asignacin. Ahora hay otras funciones para la gestin de memoria, para
mayor informacin revisar las referencias del lenguaje.
A continuacin se muestra un ejemplo del uso de memoria dinmica en la
implementacin de la funcin mystrdup que obtiene una asignacin de espacio
de memoria antes de realizar la copia a diferencia de la funcin mystrcpy que
asume que el apuntador de destino contiene un espacio asignado para realizar
la copia

Mayo 2013

107

Introduccin al
Lenguaje de Programacin C

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <malloc.h>
char *B, *A = "HOLA MUNDO";
int mystrlen(const char *s){
const char *p = s;
while(*p)
p++;
return p-s;
}
void mystrcpy(char *d,const char *f){
while(*d++=*f++);
}
char *mystrdup(const char *f){
char *p;
p = (char *)malloc(mystrlen(f)+1);
if(p!=NULL)
mystrcpy(p,f);
return p;
}
int main(void){
printf("A:%s\n",A);
printf("Longitud A:%d\n",mystrlen(A));
B = mystrdup(A);
printf("B:%s\n",B);
return 0;
}
/* --- Fin ejemplo --- */

Como se puede observar los apuntadores proporcionan el soporte


necesario para la asignacin de memoria dinmica. La asignacin
dinmica es la forma como un programa puede obtener, de forma
explcita, memoria mientras se est ejecutando. Lo cual puede resultar til
cuando el programa no conoce por anticipado las necesidades de
almacenamiento.

Mayo 2013

108

Introduccin al
Lenguaje de Programacin C

Alias, referencias pendientes y basura


Pueden existir varios problemas con el manejo de referencias en lenguaje con
apuntadores, memoria dinmica y estructurados por bloques, como es el caso de
C, y estos son: los alias, las referencias pendientes y la basura.
Alias
Un Alias ocurre cuando el mismo objeto est vinculado a dos nombres diferentes
al mismo tiempo. Esto puede ocurrir entre otras causas al hacer uso de
apuntadores.
El problema que presentan el alias son los efectos colaterales que producen, se
define como un efecto colateral de una instruccin como cualquier cambio en el
valor de una variable que persiste ms all de la ejecucin de la instruccin,
dichos efectos pueden ser altamente dainos y el uso de alias presenta
dificultades para controlarlos.
Por ejemplo:
int a = 5, *ap = &a;
*ap = 10;
printf("a: %d\n",a);

En este cdigo, la lnea 2 ha cambiado tambin el valor de a sin que en el cdigo


se haga mencin explcita de ello.
A continuacin se muestra un caso de alias con memoria dinmica

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/

Mayo 2013

109

Introduccin al
Lenguaje de Programacin C

#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv){
int *xp, *yp;
xp = (int *) malloc(sizeof(int));
*xp = 5;
yp = xp;
*yp = 10;
printf("*xp: %d\n",*xp);
return 0;
}
/* --- Fin ejemplo --- */

Referencias pendientes
Las referencias pendientes es un segundo problema que se puede presentar con
el uso de apuntadores. Una referencia pendiente es una localizacin que ha sido
desasignada del entorno, pero a la que el programa puede tener acceso
todava, es decir una localizacin puede ser accedida ms all de su tiempo de
vida.
char *i2a(int numero){
char buffer[20];
sprintf(buffer,"%d",numero);
return buffer;
}

En este cdigo, la funcin i2s ha retornado la direccin de buffer, pero el arreglo


buffer tiene un tiempo de vida igual a la ejecucin de la funcin, es decir cuando
se utilice la direccin retornada por i2a luego de la llamada el espacio de buffer
ya estar desasignado.
A continuacin se muestra un caso de referencia pendiente con memoria

Mayo 2013

110

Introduccin al
Lenguaje de Programacin C

dinmica
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv){
int *xp;
xp = (int *) malloc(sizeof(int));
*xp = 5;
free(xp);
printf("*xp: %d\n",*xp);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

111

Introduccin al
Lenguaje de Programacin C

Funciones con un nmero de parmetros variables


En C es posible crear funciones que reciban un nmero no especificado de
argumentos, un buen ejemplo puede ser la funcin printf. En el prototipo de la
funcin los puntos suspensivos () indica que la funcin recibe un nmero
variable de argumentos de cualquier tipo:
int printf(const char *, );
Las macros y definiciones necesarias para construir funciones con un nmero de
parmetros variables, se encuentran en archivo de encabezados <stdarg.h>
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdarg.h>
double avg(int n, ...){
double total = 0;
int register i;
va_list ap;
va_start(ap,n);
for(i=1;i<=n;i++)
total+=va_arg(ap,double);
va_end(ap);
return total/n;
}
int main(void){
double a=1.0,b=2.0,c=3.0,d=4.0;
printf("avg con 2 parametros:%f\n",avg(2,a,b));
printf("avg con 3 parametros:%f\n",avg(3,a,b,c));
printf("avg con 4 parametros:%f\n",avg(4,a,b,c,d));
printf("avg con 5
parametros:%f\n",avg(5,5.0,10.0,15.0,20.0,25.0));
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

112

Introduccin al
Lenguaje de Programacin C

Pase de parmetros a la funcin main


En los entornos que maneja C, hay una forma de transmitir al programa los
argumentos de la lnea de comando. Cuando se invoca al main al comienzo de
la ejecucin, se llama con dos argumentos. El primero (argc) es el nmero de
argumentos en la lnea de comando con que se invoco al programa; el segundo
(argv) es un apuntador a un arreglo de cadenas de caracteres, que contiene los
argumentos uno en cada una de las cadena.
/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
int main(int argc,char *argv[]){
if(argc>0)
printf("Argumento 1 %s\n",*argv++);
if(argc>1)
printf("Argumento 2 %s\n",*argv++);
if(argc>2)
printf("Argumento 3 %s\n",*argv++);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

113

Introduccin al
Lenguaje de Programacin C

El preprocesador
El preprocesador se ejecuta al comenzar el proceso de compilacin, es decir una
fase previa a ste, y se encarga de realizar ciertas tareas bsicas; entre estas
tareas estn la inclusin de archivos, expansin de macros y procesar de
directivas.
Las directivas del preprocesador empiezan por # y las principales son:

#include

Incluir archivos.

#define

Declara una macro o una constante

#undef

Borra una macro de la tabla de definiciones.

#if, #ifdef, #ifndef, #else, #elif y #endif


Son utilizadas para Compilacin Condicional. Se puede
preguntar por el valor de una constante o la existencia o no
de una macro. En caso de ser cierta la condicin se compila
el cdigo entre #if y #else, en caso de ser falsa se compila el
cdigo entre #else y #endif.

#error, #line, #pragma

Consideraciones sobre macros


Debido a que el preprocesador de macros trabaja por simple reemplazo, se
pueden cometer algunos errores, para evitarlos se siguen unas simples
convenciones:
Colocar parntesis alrededor de los argumentos siempre que sea posible:
Incorrecto:

#define square(x) x*x

Mejor:

#define square(x) (x)*(x)

Colocar parntesis alrededor de la expresin entera, para que el orden de las


operaciones no afecte el resultado.
Incorrecto:

Mayo 2013

#define square(x) (x)*(x)

114

Introduccin al
Lenguaje de Programacin C

Mejor:

#define square(x) ((x)*(x))

/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int main(void){
int a,b;
printf("Un entero:");
scanf("%d",&a);
printf("Otro entero:");
scanf("%d",&b);
#ifdef DEPURAR
printf("valor a:%d\n",a);
printf("valor b:%d\n",b);
#endif
printf("Maximo entre %d y %d es %d\n",a,b,MAX(a,b));
return 0;
}
/* --- Fin ejemplo --- */

Ahora trabajando con flotantes y compilacin condicional


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#define REDONDEAR(X) ((int)((X)+0.5))
#define TRUNCAR(X) ((int)(X))
#define P_DECIMAL(X) ((X)-TRUNCAR(X))
#define DEPURAR 1
char c1,c2,c3='b';
int i1,i2;
float f=3.5152,f1,f2,f3;
int main(void){

Mayo 2013

115

Introduccin al
Lenguaje de Programacin C

i1 = f1 = REDONDEAR(f);
i2 = f2 = TRUNCAR(f);
f3 = P_DECIMAL(f);
c1 = '0'+i1;
c2 = '0'+i2;
c3+=('A'-'a');
printf("+-+-+-+-+-+-+-+-+-+\n");
#ifdef DEPURAR
printf("f:%f f1:%f f2:%f f3:%f\n",f,f1,f2,f3);
printf("c1:%c c2:%c c3:%c\n",c1,c2,c3);
#endif
printf("+-+-+-+-+-+-+-+-+-+\n");
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

116

Introduccin al
Lenguaje de Programacin C

Llamadas a otros lenguajes de programacin


C soporta compilacin separada, y posteriormente se enlazan los diferentes
mdulos para crear el ejecutable, ahora no necesariamente todos los mdulos
deben estar programado en C, como es el caso que se muestra a continuacin,
donde un programa escrito en lenguaje C invoca a una funcin escrita en
fortran77.

Archivo en C
#include <stdio.h>
extern void fortfunc_(int *a, int *b);
int main(){
int a=1,b=2;
printf("Antes a:%d b:%d\n",a,b);
fortfunc_(&a, &b);
printf("Despues a:%d b:%d\n",a,b);
return 0;
}

Archivo en Fortran77
subroutine fortfunc(i,j)
integer i
integer j
i=5
j=6

Mayo 2013

117

Introduccin al
Lenguaje de Programacin C

return
end
Salida
E:\Pruebas
Antes a:1 b:2
Despues a:5 b:6

Mayo 2013

118

Introduccin al
Lenguaje de Programacin C

Caso de estudio: implementar un comando del sistema


El lenguaje C es utilizado en para programar partes del sistema de operacin y/o
utilidades, a continuacin se muestra la implementacin de un comando del
sistema cat que escribir a la salida estndar el contenido de cada uno de los
archivos dados como argumentos, en el mismo orden en el que fueron dados. Si
no se especifica ningn archivo, leer slo de la entrada estndar
/*
* UCAB
* Introduccion al Lenguaje C
* Comando cat como en UNIX
*/
#include <stdio.h>
#include <stdlib.h>
/*
* Copia el archivo fp en la salida estandar
*/
void filecopy(FILE *fp){
int c;
while((c=getc(fp))!=EOF)
putc(c,stdout);
}
int main(int argc, char* argv[]){
FILE *fp;
if(argc==1)
filecopy(stdin);
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"cat: can't open %s\n",*argv);
exit(EXIT_FAILURE);
}
else{
filecopy(fp);
fclose(fp);
}
exit(EXIT_SUCCESS);
}
/* fin del ejemplo */

Mayo 2013

119

Introduccin al
Lenguaje de Programacin C

Algoritmos y aplicaciones
A continuacin se muestran algunos programas que pueden ser de inters

Implementar conjuntos con bits


/*
* UCAB Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#define METER(B,S) (B|=1<<S)
#define SACAR(B,S)(B&=~(1<<S))
#define PERTENECE(B,S)(B>>S&1)
typedef unsigned long Conjunto;
Conjunto C_vaciar(void){
return 0;
}
Conjunto C_meter(Conjunto c, int e){
if(e>=0 && e<sizeof(Conjunto)*8)
return (c|1<<e);
return c;
}
Conjunto C_sacar(Conjunto c, int e){
if(e>=0 && e<sizeof(Conjunto)*8)
return (c&~(1<<e));
return c;
}
int C_pertenece(Conjunto c,int e){
if(e>=0 && e<sizeof(Conjunto)*8)
return (c>>e&1);
return 0;
}
void C_imprime(Conjunto c){
register int i;
printf("{ ");
for(i=0;i<sizeof(Conjunto)*8;i++,c>>=1)
if(c&1)

Mayo 2013

120

Introduccin al
Lenguaje de Programacin C

printf("%d ",i);
printf("}\n");
}
Conjunto C_union(Conjunto A, Conjunto B){
return A|B;
}
Conjunto C_interseccion(Conjunto A, Conjunto B){
return A&B;
}
int main(void){
char *r[2]={"No","Si"};
Conjunto A,B,C;
A=C_vaciar();
B=C_vaciar();
A=C_meter(A,0);
A=C_meter(A,5);
A=C_meter(A,10);
B=C_meter(B,10);
B=C_meter(B,15);
C=C_union(A,B);
printf("A:");
C_imprime(A);
printf("B:");
C_imprime(B);
printf("A Union B:");
C_imprime(C);
printf("A Interseccion B:");
C_imprime(C_interseccion(A,B));
C=C_sacar(C,10);
printf("C:");
C_imprime(C);
printf("%d %s pertenece a C",5,r[C_pertenece(C,5)]);
return 0;
}
/* --- Fin ejemplo --- */

Mayo 2013

121

Introduccin al
Lenguaje de Programacin C

Implementar bicolas con arreglos


/*
* UCAB - Guayana
* Introduccion al Lenguaje C
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct bicola{
int capacidad;
int *elementos;
int cuenta;
int primero;
int ultimo;
} *BiCola;
void FatalError(char *msg){
fprintf(stderr,msg);
exit(1);
}
BiCola inicializarBiCola(int MaxElementos){
BiCola bp;
if(MaxElementos < 5)
MaxElementos=7;
if((bp = (BiCola)malloc(sizeof(struct bicola)))==NULL)
FatalError("Memoria Insuficiente!!!");
if((bp->elementos = malloc((MaxElementos)*sizeof(int)))==NULL)
FatalError("Memoria Insuficiente!!!");
bp->capacidad = MaxElementos;
bp->cuenta = 0;
bp->primero = 1;
bp->ultimo = 0;
return bp;
}
void vaciarBicola(BiCola bp){
bp->cuenta = 0;
bp->primero = 1;
bp->ultimo = 0;;
}
int BiColaVacia(BiCola bp){
return bp->cuenta == 0;
}
int BiColaLlena(BiCola bp){

Mayo 2013

122

Introduccin al
Lenguaje de Programacin C

return bp->cuenta == bp->capacidad;


}
int BiColaPrimerElemento(BiCola bp, int *elemento){
if(bp->cuenta == 0)
return 0;
*elemento = bp->elementos[bp->primero];
return 1;
}
int BiColaUltimoElemento(BiCola bp, int *elemento){
if(bp->cuenta == 0)
return 0;
*elemento = bp->elementos[bp->ultimo];
return 1;
}
int BiColaPonerFrente(BiCola bp,int elemento){
if(bp->cuenta==bp->capacidad)
return 0;
bp->cuenta++;
bp->primero = (bp->primero==0?bp->capacidad-1:bp->primero-1);
bp->elementos[bp->primero] = elemento;
return 1;
}
int BiColaPonerAtras(BiCola bp,int elemento){
if(bp->cuenta==bp->capacidad)
return 0;
bp->cuenta++;
bp->ultimo=(bp->ultimo+1)%bp->capacidad;
bp->elementos[bp->ultimo]=elemento;
return 1;
}
int BiColaQuitarFrente(BiCola bp,int *elemento){
if(bp->cuenta==0)
return 0;
bp->cuenta--;
*elemento=bp->elementos[bp->primero];
bp->primero=(bp->primero+1)%bp->capacidad;
return 1;
}
int BiColaQuitarAtras(BiCola bp,int *elemento){
if(bp->cuenta==0)
return 0;
bp->cuenta--;
*elemento=bp->elementos[bp->ultimo];
bp->ultimo = (bp->ultimo==0?bp->capacidad-1:bp->ultimo-1);
return 1;
}

Mayo 2013

123

Introduccin al
Lenguaje de Programacin C

int main(void) {
int i=0;
BiCola mbp;
mbp = inicializarBiCola(10);
for(i=0;i<6;i++){
BiColaPonerFrente(mbp,i);
i++;
BiColaPonerAtras(mbp,i);
}
while(BiColaQuitarFrente(mbp,&i))
printf("%d ",i);
printf("\n");
for(i=0;i<6;i++){
BiColaPonerFrente(mbp,i);
i++;
BiColaPonerAtras(mbp,i);
}
while(BiColaQuitarAtras(mbp,&i))
printf("%d ",i);
printf("\n");
for(i=0;i<11;i++)
BiColaPonerAtras(mbp,i);
while(BiColaQuitarFrente(mbp,&i))
printf("%d ",i);
printf("\n");
for(i=0;i<11;i++)
BiColaPonerFrente(mbp,i);
while(BiColaQuitarAtras(mbp,&i))
printf("%d ",i);
printf("\n");
for(i=0;i<11;i++)
BiColaPonerFrente(mbp,i);
while(BiColaQuitarFrente(mbp,&i))
printf("%d ",i);
printf("\n");
for(i=0;i<11;i++)
BiColaPonerAtras(mbp,i);
while(BiColaQuitarAtras(mbp,&i))
printf("%d ",i);
return EXIT_SUCCESS;
}

Mayo 2013

124

Introduccin al
Lenguaje de Programacin C

Bibliografa recomendada

Kernigan Brian & Ritchie Dennis, El lenguaje de programacin C, Segunda


edicin, Prentice Hall, 1988.

Deitel P.J. & Deitel H.M., Como programar en C/C++, Prentice Hall, 1995.

American National Standards Institute, Programming Language C, ANSY


X3.159-1989.

Schildt Herbert, C Manual de referencia, Cuarta edicin, McGraw-Hill, 2001.

Joyanes A. Luis, Castillo S. Andrs, Snchez G. Lucas & Zahonero M. Ignacio,


Programacin en C Libro de Problemas, McGraw-Hill, 2002.

Kernigan Brian & Pike Rob, La prctica de la programacin, Prentice Hall,


2000.

Louden Kenneth, Lenguajes de programacin Principios y Prctica,


Segunda edicin, Thonsom, 2004

Mayo 2013

125

Introduccin al
Lenguaje de Programacin C

ANEXOS

Mayo 2013

126

Introduccin al
Lenguaje de Programacin C

Anexo A
Ejemplo de algunas declaraciones que pueden ser de ayuda y utilidad para
entender o hacer declaraciones, sobre todo cuando se utilizan apuntadores.
int i; // integer variable
int *p; // pointer to integer variable
int a[]; // array of integer
int f(); // function with return value integer
int **pp; // pointer to pointer to integer
int (*pa)[]; // pointer to an array of integer
int (*pf)(); // pointer to a function with return value integer
int *ap[]; // array of pointers to integer
int *fp(); // function, which returns a pointer to an integer
int ***ppp; // pointer to a pointer to a pointer to integer
int (**ppa)[]; // pointer to a pointer to an array of integer
int (**ppf)(); // pointer to a pointer to a function with return value integer
int *(*pap)[]; // pointer to an array of pointers to integer
int *(*pfp)(); // pointer to function with return value pointer to integer
int **app[]; // array of pointer to pointer to integer
int (*apa[])[];// array of pointers to array of integer
int (*apf[])();// array of pointers to functions with return value integer
int ***fpp(); // function with return value pointer to pointer to pointer to int
int (*fpa())[];// function with return value pointer to array of integers
int (*fpf())();// function with return value pointer to function, which returns an integer

Mayo 2013

127

Introduccin al
Lenguaje de Programacin C

Manual de gcc
GCC(1)

GNU Tools

GCC(1)

NAME
gcc, g++ - GNU project C and C++ Compiler (gcc-2.96)
SYNOPSIS
gcc [ option | filename ]...
g++ [ option | filename ]...
WARNING
The information in this man page is an extract from the
full documentation of the GNU C compiler, and is limited
to the meaning of the options.
This man page is not kept up to date except when volunteers want to maintain it.
If you find a discrepancy
between the man page and the software, please check the
Info file, which is the authoritative documentation.
If we find that the things in this man page that are out
of date cause significant confusion or complaints, we will
stop distributing the man page. The alternative, updating
the man page when we update the Info file, is impossible
because the rest of the work of maintaining GNU CC leaves
us no time for that. The GNU project regards man pages as
obsolete and should not let them take time away from other
things.
For complete and current documentation, refer to the Info
file `gcc' or the manual Using and Porting GNU CC (for
version 2.0). Both are made from the Texinfo source file
gcc.texinfo.
DESCRIPTION
The C and C++ compilers are integrated.
Both process
input files through one or more of four stages: preprocessing, compilation, assembly, and linking. Source filename suffixes identify the source language, but which name
you use for the compiler governs default assumptions:
gcc

assumes preprocessed (.i) files are C and assumes C


style linking.

g++

assumes preprocessed (.i) files are C++ and assumes


C++ style linking.

Suffixes of source file names indicate


kind of processing to be done:

Mayo 2013

the

language

and

128

Introduccin al
Lenguaje de Programacin C

.c
.C
.cc
.cxx
.m
.i
.ii
.s
.S
.h

C source; preprocess, compile, assemble


C++ source; preprocess, compile, assemble
C++ source; preprocess, compile, assemble
C++ source; preprocess, compile, assemble
Objective-C source; preprocess, compile, assemble
preprocessed C; compile, assemble
preprocessed C++; compile, assemble
Assembler source; assemble
Assembler source; preprocess, assemble
Preprocessor file; not usually named on command line

Files with other suffixes are passed to the linker.


mon cases include:
.o
.a

Com-

Object file
Archive file

Linking is always the last stage unless you use one of the
-c, -S, or -E options to avoid it (or unless compilation
errors stop the whole process). For the link stage, all
.o files corresponding to source files, -l libraries,
unrecognized filenames (including named .o object files
and .a archives) are passed to the linker in command-line
order.
OPTIONS
Options must be separate: `-dr' is
`-d -r '.

quite

different

from

Most `-f' and `-W' options have two contrary forms: -fname
and -fno-name (or -Wname and -Wno-name).
Only the nondefault forms are shown here.
Here is a summary of all the options, grouped by type.
Explanations are in the following sections.
Overall Options
-c -S -E -o file -pipe -v -x language
Language Options
-ansi -fcond-mismatch -fdollars-in-identifiers
-fexternal-templates -fno-asm -fno-builtin -fhosted
-fno-hosted -ffreestanding -fno-freestanding
-fno-strict-prototype -fsigned-bitfields
-fsigned-char -funsigned-bitfields -funsigned-char
-fwritable-strings -traditional -traditional-cpp
-trigraphs
Warning Options
-fsyntax-only -pedantic -pedantic-errors -w -W
-Wall -Waggregate-return -Wcast-align -Wcast-qual
-Wchar-subscript -Wcomment -Wconversion -Werror

Mayo 2013

129

Introduccin al
Lenguaje de Programacin C

-Wformat -Wid-clash-len -Wimplicit -Wimplicit-int


-Wimplicit-function-declaration -Winline
-Wlong-long -Wmain -Wmissing-prototypes
-Wmissing-declarations -Wnested-externs -Wno-import
-Wparentheses -Wpointer-arith -Wredundant-decls
-Wreturn-type -Wshadow -Wstrict-prototypes -Wswitch
-Wtraditional -Wtrigraphs -Wuninitialized -Wunused
-Wunused-function -Wunused-label -Wunused-parameter
-Wunused-variable -Wunused-value -Wwrite-strings
Debugging Options
-a -dletters -fpretend-float -g -glevel -gcoff
-gxcoff -gxcoff+ -gdwarf -gdwarf+ -gstabs -gstabs+
-ggdb -p -pg -save-temps -print-file-name=library
-print-libgcc-file-name -print-prog-name=program
Optimization Options
-fcaller-saves -fcse-follow-jumps -fcse-skip-blocks
-fdelayed-branch -felide-constructors
-fexpensive-optimizations -ffast-math -ffloat-store
-fforce-addr -fforce-mem -finline-functions
-fkeep-inline-functions -fmemoize-lookups
-fno-default-inline -fno-defer-pop
-fno-function-cse -fno-inline -fno-peephole
-fomit-frame-pointer -frerun-cse-after-loop
-fschedule-insns -fschedule-insns2
-fstrength-reduce -fthread-jumps -funroll-all-loops
-funroll-loops -O -O2 -O3
Preprocessor Options
-Aassertion -C -dD -dM -dN -Dmacro[=defn] -E -H
-idirafter dir -include file -imacros file -iprefix
file -iwithprefix dir -M -MD -MM -MMD -nostdinc -P
-Umacro -undef
Assembler Option
-Wa,option
Linker Options
-llibrary -nostartfiles -nostdlib -static -shared
-symbolic -Xlinker option -Wl,option -u symbol
Directory Options
-Bprefix -Idir -I- -Ldir
Target Options
-b machine -V version
Configuration Dependent Options
M680x0 Options
-m68000 -m68020 -m68020-40 -m68030 -m68040 -m68881
-mbitfield -mc68000 -mc68020 -mfpa -mnobitfield

Mayo 2013

130

Introduccin al
Lenguaje de Programacin C

-mrtd -mshort -msoft-float


VAX Options
-mg -mgnu -munix
SPARC Options
-mepilogue -mfpu -mhard-float -mno-fpu
-mno-epilogue -msoft-float -msparclite -mv8
-msupersparc -mcypress
Convex Options
-margcount -mc1 -mc2 -mnoargcount
AMD29K Options
-m29000 -m29050 -mbw -mdw -mkernel-registers
-mlarge -mnbw -mnodw -msmall -mstack-check
-muser-registers
M88K Options
-m88000 -m88100 -m88110 -mbig-pic
-mcheck-zero-division -mhandle-large-shift
-midentify-revision -mno-check-zero-division
-mno-ocs-debug-info -mno-ocs-frame-position
-mno-optimize-arg-area -mno-serialize-volatile
-mno-underscores -mocs-debug-info
-mocs-frame-position -moptimize-arg-area
-mserialize-volatile -mshort-data-num -msvr3 -msvr4
-mtrap-large-shift -muse-div-instruction
-mversion-03.00 -mwarn-passed-structs
RS6000 Options
-mfp-in-toc -mno-fop-in-toc
RT Options
-mcall-lib-mul -mfp-arg-in-fpregs -mfp-arg-in-gregs
-mfull-fp-blocks -mhc-struct-return -min-line-mul
-mminimum-fp-blocks -mnohc-struct-return
MIPS Options
-mcpu=cpu type -mips2 -mips3 -mint64 -mlong64
-mlonglong128 -mmips-as -mgas -mrnames -mno-rnames
-mgpopt -mno-gpopt -mstats -mno-stats -mmemcpy
-mno-memcpy -mno-mips-tfile -mmips-tfile
-msoft-float -mhard-float -mabicalls -mno-abicalls
-mhalf-pic -mno-half-pic -G num -nocpp
i386 Options
-m486 -mno-486 -msoft-float -mno-fp-ret-in-387
HPPA Options
-mpa-risc-1-0 -mpa-risc-1-1 -mkernel -mlong-calls
-mdisable-fpregs -mdisable-indexing

Mayo 2013

131

Introduccin al
Lenguaje de Programacin C

-mtrailing-colon
i960 Options
-mcpu-type -mnumerics -msoft-float
-mleaf-procedures -mno-leaf-procedures -mtail-call
-mno-tail-call -mcomplex-addr -mno-complex-addr
-mcode-align -mno-code-align -mic-compat
-mic2.0-compat -mic3.0-compat -masm-compat
-mintel-asm -mstrict-align -mno-strict-align
-mold-align -mno-old-align
DEC Alpha Options
-mfp-regs -mno-fp-regs -mno-soft-float -msoft-float
System V Options
-G -Qy -Qn -YP,paths -Ym,dir
Code Generation Options
-fcall-saved-reg -fcall-used-reg -ffixed-reg
-finhibit-size-directive -fnonnull-objects
-fno-common -fno-ident -fno-gnu-linker
-fpcc-struct-return -fpic -fPIC -freg-struct-return
-fshared-data -fshort-enums -fshort-double
-fvolatile -fvolatile-global -fverbose-asm

Mayo 2013

132

You might also like