el lenguaje de programaci on c (explicaci on de las ... · el lenguaje de programaci on c ... en...

35
El lenguaje de programaci´ on C (Explicaci´ on de las transparencias) (C) Javier Miranda 1996-2004 Reservados todos los derechos Esta colecci´ on de notas es un material complementario de la colecci’on de transparencias. Forma parte del contenido del libro “Dise˜ no de Software con C y UNIX (Volumen 1)”, J.Miranda (1996), con ISBN 84-87526-45-4. 18 de febrero de 2004 1

Upload: vuongkhue

Post on 22-Jul-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje de programacion C

(Explicacion de las transparencias)

(C) Javier Miranda 1996-2004Reservados todos los derechos

Esta coleccion de notas es un material complementario de lacolecci’on de transparencias. Forma parte del contenido

del libro “Diseno de Software con C y UNIX (Volumen 1)”,J.Miranda (1996), con ISBN 84-87526-45-4.

18 de febrero de 2004

1

Page 2: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 1

4. El lenguaje de programacion C

4.1. Historia de C

El nacimiento de C esta muy ligado al nacimiento de Unix en los laboratorios Bell.En 1968 Thompson creo un grupo para investigar alternativas al sistema operativoMultics y desarrollo Unix sobre un computador DEC PDP-7 (8k-18bit palabras dememoria, sin software disponible). Escribio la version original de Unix mediante macrosy un ensamblador cruzado (cargando el ejecutable mediante una cinta). De esta formadesarrollo: el nucleo primitivo de Unix, un editor basico, un ensamblador sencillo quegeneraba siempre el ejecutable en el fichero “a.out”, un interprete de comandos basico ylos comandos basicos del S.O. (rm, cat, cp). A partir de este momento ya pudo escribirlos programas directamente en Unix.

En 1969 Thompson intenta utilizar FORTRAN para escribir el S.O., pero lo aban-dona rapidamente y crea el lenguaje B (simplificacion del lenguaje BCPL). B es unlenguaje para programacion de sistemas, pequeno, con descripcion compacta, facil-mente traducible y cercano a la maquina. Sin embargo, Thompson comprobo que B noera adecuado para reescribir Unix y sus utilidades.

En 1970 Thompson continuo el desarrollo de Unix sobre DEC PDP-11 (24k), y ree-scribio Unix en ensamblador del PDP-11 utilizando 12k para el nucleo de Unix y 12kcomo disco RAM.

En 1971 Unix comenzo a tener usuarios (que programaban en ensamblador con rutinasde biblioteca). De esta forma Steve Johnson creo yacc. Este mismo ano Thompsonmodifico B y creo el lenguaje NB (introduciendo basicamente los tipos de datos int,char, los punteros y los arrays).

En 1972 introdujeron en el lenguaje un preprocesador y realizaron pequenas modifi-caciones en la evaluacion de las expresiones e introdujeron nuevos operadores.

En 1973 se creo C, Thompson reescribio Unix en C e instalo C en otras arquitecturas(Honeywell 635, IBM 360/370) y Lesk desarrollo un modulo de E/S estandar.

En 1978 Kernighan y Ritchie publicaron el libro The C programming language. (Kernighanse encargo de la exposicion de C y Ritchie de la interfaz con Unix y el apendice —manual de referencia tecnica de C—) y Steve Johnson desarrollo pcc (un compiladorde C facilmente transportable).

En 1979 Johnson crea lint adaptando pcc.

En 1983 se crea el comite X2J11 para la creacion del estandar de C.

En 1989 C se convierte en estandar ISO/IEC 9899-1990

A partir de C se han desarrollado los siguientes lenguajes: Objetive C [Cox, 86], C++[Stroustrup, 86], C Concurrente[Gehani, 89], C* [Thinking, 90], C Concurrente Toler-ante a fallos [Cmelik, Gehani, Roome].

Page 3: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 2

4.2. El compilador de C

El compilador de C consta internamente de 4 programas: el preprocesador, el com-pilador, un ensamblador y un enlazador. El preprocesador se encarga de eliminar loscomentarios del programa y de interpretar sus comandos. Tras el preprocesador se eje-cuta el compilador, que genera un fichero equivalente en ensamblador. Este fichero seensambla para generar el fichero objeto (.o). Finalmente el enlazador combina todoslos ficheros objeto especificados en la lınea de comando (incluyendo los ficheros objetode las bibliotecas) y genera el fichero ejecutable.

Ejemplos:

1. Llamar al preprocesador, compilador, ensamblador, enlazador y generar el eje-cutable en el fichero a.out.

cc ejemplo.c

2. Llamar al preprocesador, compilador y ensamblador para generar los ficherosobjeto asociados a los ficheros main.c, getline.c e index.c. A continuacion llamaral enlazador pasandole los tres ficheros objeto para generar el fichero ejecutablemyprog.

cc main.c getline.c index.c -o myprog

3. Llamar al preprocesador, compilador y ensamblador para generar el fichero objetoasociado al fichero main.c. A continuacion llamar al enlazador pasandole los tresficheros objeto para generar el fichero ejecutable.

cc main.c getline.o index.o

Page 4: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 3

4.3. El preprocesador

El preprocesador de C es un procesador de macros simple que conceptualmente procesael fichero fuente de un programa C antes de su compilacion. Se controla mediante lıneasde comandos (lıneas del programa fuente C) que pueden ir en cualquier parte del ficherofuente y deben cumplir las siguientes reglas:

1. Deben comenzar comienzan con el caracter #.

2. Cada orden debe ocupar una lınea.

4.3.1. Macros

El comando #define introduce una definicion de macro. Una macro asocia un iden-tificador a una cadena (string). El preprocesador sustituye las ocurrencias de dichoidentificador por la cadena de reemplazo (sustituyendo los parametros formales queaparezcan en el cuerpo de la macro por el valor de los parametros proporcionado enel momento de la invocacion de la macro). El ambito de las macros va desde el puntode su definicion hasta el final del fichero. Las macros pueden declararse desde la lıneacomandos (cuando se invoca el compilador). Por ejemplo:

cc -DM68000=1 file.c

. . . define la macro M68000 con el valor 1 antes de compilar el fichero file.c.

El comando #undef borra la definicion de una macro previamente definida.

Page 5: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 4

4.3.2. Compilacion condicional

La compilacion condicional se utiliza para incorporar u omitir de forma selectiva unasecuencia de sentencias. Por convenio los ficheros que se incluyen tienen el sufijo .h. Seutiliza para incluir sentencias de depuracion de los programas C y para aumentar laportabilidad de los programas.

4.3.3. Inclusion de ficheros

El comando #include hace que el contenido del fichero especificado se procese comosi estuviese ubicado en el lugar del comando. Existen dos formas de nombrar el fichero,y difieren en donde esta almacenado el fichero especificado.

#include "fichero.h" /* Busca en el directorio actual */

#include <fichero.h> /* Busca el sitio estandar /usr/include */

Este comando se utiliza generalmente para acceder a grupos de macros. De esta forma,varios ficheros ven las mismas constantes. Sin embargo, debe tenerse especial cuidadocon los posibles bucles y duplicaciones de macros. La forma correcta de evitar estosproblemas consiste en utilizar el comando #ifndef de la siguiente forma:

#ifndef MAX

#define MAX 50

/* Resto del fichero de definiciones */

#endif

Page 6: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 5

4.4. Introduccion a C

Veamos con un ejemplo algunas de las caracterısticas del lenguaje C:

1. C es un lenguaje de formato libre (excepto los comandos del preprocesador).

2. Los comentarios pueden ponerse en cualquier sitio donde pueda ponerse un espacioen blanco. Comienzan mediante /* y terminan con */.

3. Es un lenguaje sensible a mayusculas y minusculas. Por convenio se suele progra-mar utilizando MAYUSCULAS para las CONSTANTES y minusculas para lasvariables.

4. Los identificadores de C estan formados por una secuencia de letras, digitos y .El primer caracter debe ser una letra o .

5. Las palabras reservadas de C son:

PALABRAS CLAVE (en minuscula)

-----------------------------

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

- Algunas implementaciones tambien reservan fortran

y asm.

- const, signed y volatile son palabras nuevas de

C-ANSI

- enum y void son nuevas con respecto a la primera

version de C.

6. Los programas C se estructuran mediante funciones.

Los parametros se pasan siempre por valor.

La funcion main es necesaria en todo programa (ya que es la primera enejecutarse) y puede tener parametros (los veremos en la seccion 4.13.5).

7. Las variables pueden inicializarse en la declaracion.

8. La finalizacion del programa ocurre cuando:

Se finaliza main.

Se ejecuta una sentencia exit().

Ocurre una interrupcion del programa (externa, interna).

Page 7: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 6

4.5. Tipos de datos

C tiene cuatro tipos de datos basicos: caracter (char), entero (int), flotante de simpleprecision (float) y flotante de doble precision (double). Ademas tiene tres cualificadoresque pueden aplicarse a los tipos basicos para ajustar la precision de los tipos basicos:short, long y unsigned (aritmetica modulo 2N , siendo N el numero de bits). Los rangosestan definidos por la implementacion y son especificados en el fichero <limits.h>. Sise utiliza un cualificador (short, long, unsigned) y se omite el tipo, se presupone quela variable es de tipo int.

long int factorial;

unsigned int natural;

signed char c; /* -127..127 */

short int dia,mes;

4.6. Constantes

Constantes tipo caracter.

ascii \’{A}’ octal ’\101’ hex ’\x41’

Constantes tipo string. Son una secuencia de caracteres entre comillas dobles.Las strings adyacentes son automaticamente concatenadas en una unica string.C utiliza el caracter null (’\0’) como terminador de strings.

Constantes tipo entero. El tipo de una constante entera depende de su forma,valor y sufijo1.

decimal 1234 12L 12U

octal (comienzan por 0) 015 015L 015U

hex 0x4f 0x4f3

Constantes tipo float. Su sintaxis es: int.fraccion [ E [+|-]int[F|L], significandolos sufijos F y L float y long double respectivamente. Puede omitirse:

• La parte entera o la parte fraccionaria (pero no ambas).

• El punto decimal o el exponente (no ambos).

1Si no tiene sufijo adopta el primero de los siguientes tipos: si es decimal adopta int, long int, unsigned

long int; si es octal o hex adopta int, unsigned int, long int, unsigned long int.

Page 8: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 7

4.7. Operadores y expresiones

Aritmeticos: Debe tenerse en cuenta que la division entera trunca, y que el resto(operador modulo) adopta el mismo signo que el dividendo. Toda la aritmeticaentera se realiza al menos con rango int (short int es convertido automaticamenteen int, lo que se denomina promocion integral). En expresiones mixtas se realizaconversion automatica al mayor tamano.

Relacionales. Adoptan los valores 0 para falso y 1 para verdadero.

Logicos.

Autoincremento, autodecremento. Existen cuatro posibilidades:

++variable; Preincremento;

--variable: Predecremento

variable++: Postincremento;

variable--: Postdecremento

Cuidado con los efectos laterales.

Asignacion. Existen dos tipos de asignacion:

1. Asignacion multiple. Operador asociativo por la izquierda que realiza con-versiones de tipo implıcitas.

a=b=c+d ===> a=(b=(c+d))

2. Asignacion compuesta (a op= b). Puede utilizarse con:

• Cualquiera de los operadores aritmeticos.

• Todos los operadores de nivel de bit excepto el complemento a 1.

La asignacion compuesta tiene las siguientes ventajas:

a) Concisa.

b) Se corresponde mejor con la forma en que piensa la gente. Decimos suma2 a i o incrementa i en 2, no toma i, sumale 2 y vuelve a colocar elresultado en i.

c) En expresiones complicadas hace el codigo mas facil de comprender, yaque el lector no necesita comprobar si dos expresiones complicadas sonrealmente la misma. Por ejemplo:

yyval[yypv[p3+p4] + yypv[p1+p2]] += 2

d) Puede ayudar al compilador a producir un codigo mas eficiente.

Expresion condicional: Evalua la expresion e1. Si es cierto, evalua la expresion e2y toma el resultado como el valor de la expresion condicional; si es falso, evaluala expresion e3 y toma este resultado como el valor de la expresion condicional.

Operador coma: Evalua la primera expresion (comenzando por la izquierda) ydescarta el resultado; a continuacion evalua la siguiente expresion y toma estevalor como el resultado de la expresion.

Operador sizeof(): Operador unitario que devuelve un entero igual al tamano enbytes de cualquier objeto.

Page 9: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 8

Precedencia de operadores (ver tabla). Puede obviarse si no se evitan los parente-sis.

Conversion de tipos. Se puede forzar la conversion explıcita del tipo coaccionada”deuna expresion mediante una construccion denominada cast. El operador cast tienela misma precedencia que cualquier otro operador unitario2.

4.7.1. Orden de evaluacion de expresiones

C no especifica en que orden se evaluan los operandos de un operador. Por ejemplo,en una sentencia como x = f()+g(), f puede ser evaluado antes que g o viceversa.Entonces, si f o g alteran alguna variable externa, de la cual depende la otrafuncion, x puede depender del orden de evaluacion.

Tampoco especifica el orden de evaluacion de los argumentos de una funcion estaespecificado. Asi, la sentencia:

printf ("%d %d\n", ++n, f(n) );

puede producir diferentes resultados en distintas maquinas, segun que n sea in-crementado antes o despues de la llamada a f(). La solucion consiste en escribir

++n;

printf ("%d %d\n", n, f(n) );

2Existe un punto oscuro en la conversion de caracteres a enteros. El lenguaje no especifica si las variables

de tipo char tienen signo o no. De esta forma, dependiendo de las caracterısticas de la arquitectura de cada

maquina puede producir un entero negativo o no.

Page 10: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 9

4.8. Control de flujo

Todas las sentencias de control de flujo de C estan asociadas a una unica sentencia. Sise desea asociarlas a un bloque debe crearse un nuevo ambito (mediante { }).

Sentencias condicionales

1. IF: El resultado de evaluar la expresion logica es un entero donde cualquiervalor diferente de 0 se interpreta como verdadero. Se asocia else al if masinterno.

2. SWITCH: Todas las alternativas deben ser diferentes. Debe combinarse conla sentencia BREAK.

Sentencias iterativas

1. WHILE.

2. DO-WHILE.

3. FOR.

expr1;

for (expr1; expr2; expr3) === while (expr2) {

sentencia; sentencia;

expr3;

}

Puede omitirse cualquiera de las expresiones.

Sentencias de bifurcacion

1. BREAK: Sale de la sentencia SWITCH, WHILE o FOR mas interna.

2. CONTINUE: Salta a reevaluar la condicion del bucle mas interno.

3. GOTO: Salto incondicional.

Page 11: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 10

4.9. Funciones

Un programa C consta de 1 o mas funciones. Un programa completo C tiene unafuncion denominada main().

C no permite definir funciones dentro de funciones.

La finalizacion de la funcion ocurre cuando se llega al final de la funcion (}) o seejecuta una sentencia return().

Los parametros se pasan siempre por valor.

Retornan por defecto un valor de tipo entero. Las funciones que no devuelvennada se definen de tipo void.

Las funciones C pueden ser recursivas.

Page 12: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 11

4.10. Variables

Las variables de C pueden ser:

Externas: Son las que se definen fuera de cualquier funcion y, por tanto, sonpotencialmente utilizables por muchas funciones. El campo de validez de unavariable externa abarca desde el punto de su declaracion en un archivo fuentehasta el fin del archivo. Si se ha de hacer referencia a una variable externa antesde su definicion o si esta definida en un archivo fuente que no es aquel en que seusa, es obligatoria una declaracion extern.

Automaticas: Son las definidas dentro de las funciones.

Estaticas: Las variables estaticas (static) pueden ser internas o externas:

• Las variables estaticas internas son locales a una funcion en la misma formaque las automaticas pero, a diferencia de ellas, su existencia es permanente,en lugar de aparecer y desaparecer al activar la funcion. Esto significa quelas variables estaticas internas proporcionan un medio de almacenamientopermanente y privado a una funcion.

• Las variables estaticas externas son accesibles en el resto del archivo fuente enel que esta declarada, pero no en otro. Por tanto, el almacenamiento estaticoexterno proporciona un medio de almacenamiento permanente y privado aun archivo (de hecho, no habra conflictos con los mismos nombres en otrosarchivos del mismo programa).

Registro: Una declaracion register avisa al compilador que la variable sera muyusada. Cuando es posible se colocan en los registros de la maquina, lo que produceprogramas mas cortos y rapidos.

Existen algunas restricciones en las variables registro, que reflejan la realidad delhardware subyacente:

• Pocas variables de cada funcion se pueden mantener en registros.

• Solo se permiten algunos tipos.

• La palabra register se ignora si hay declaraciones excesivas o no permitidas.

• No es posible tomar la direccion de una variable registro.

Las variables de C pueden definirse en una forma estructurada en bloques. Las declara-ciones de variables (incluyendo inicializaciones) se colocan despues de la llave de aper-tura que introduce cualquier sentencia compuesta, no solamente al comienzo de unafuncion. Las variables declaradas ası se solapan con cualquier variable del mismo nom-bre en bloques externos, y permanecen hasta que se alcanza la llave de cierre.

Page 13: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 12

4.10.1. Reglas de inicializacion de variables

En ausencia de una inicializacion explıcita, se garantiza que las variables externasy estaticas tendran inicialmente el valor cero. Las variables automaticas y registrotienen valores indefinidos (”basura”).

Las variables externas y estaticas solo pueden inicializarse mediante una expresionconstante; la inicializacion se realiza una sola vez, conceptualmente antes de quecomience la ejecucion del programa.

Las variables automaticas y registro pueden inicializarse a valores no constantes(cualquier expresion, incluyendo llamadas a funciones), y se inicializan cada vezque se entra en la funcion o bloque.

Page 14: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 13

4.11. Entrada/salida

La entrada/salida basica de caracteres se realiza mediante dos macros definidas en<stdio.h>. Son:

putchar(char c)

int getchar()

La entrada/salida de strings se realiza mediante las funciones:

gets(char *linea)

puts(const char *linea)

La entrada/salida formateada se realiza mediante las funciones:

printf(char *formato, arg1, arg2, ...)

scanf(char *formato, arg1, arg2, ...)

La conversion de strings a tipos basicos y viceversa se realiza mediante las funciones:

sprintf(char *s, const char *format, ...)

sscanf(char *s, const char *format, ...)

Page 15: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 14

4.12. Estructuras de datos

4.12.1. Sinonimo (alias)

C permite crear sinonimos de tipos de datos. Las principales razones para utilizar estetipo de declaraciones son:

1. Facilitar la documentacion (y legibilidad) de un programa.

2. Asociar nombres mas cortos a identificadores largos.

3. Parametrizar un programa contra problemas de portabilidad. Si se utiliza typedefcon los tipos de datos que pueden ser dependientes de la instalacion, solo setendran que cambiar los typedef cuando se lleve el programa a otro computador.Una practica comun es emplear typedef para las cantidades enteras y luego hacerlas elecciones apropiadas de short, int y long en cada computadora.

4. Utilizar algun programa que aproveche la informacion contenida en las declara-ciones typedef para realizar comprobaciones de tipos en el programa (por ejemplo,lint).

4.12.2. Enumerado

A menos que se le asignen valores explıcitos, el compilador asigna valores enteros con-stantes sucesivos comenzando por cero. La declaracion de un enumerado tiene las sigu-ientes ventajas frente a las declaraciones equivalentes mediante macros:

1. El compilador puede detectar errores en las expresiones y asignaciones.

2. El depurador puede imprimir el valor simbolico (en vez del valor entero).

Page 16: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 15

4.12.3. Array

Declaracion: Existen dos formas de declaracion de arrays:

1. Explıcita: cuando se especifica el numero de elementos del array.

2. Implıcita: cuando el numero de elementos del array lo calcula el compilador.

Los arrays multidimensionales se declaran mediante notacion de vectores (no ma-tricial) y se almacenan por filas.

Acceso. El ındice de acceso del array es una expresion entera. Es responsabilidaddel programador garantizar que el valor del ındice esta dentro de los lımites delarray.

Page 17: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 16

4.12.4. Estructura (Registro)

Declaracion. Una estructura es un conjunto de una o mas variables, posiblementede tipos diferentes, agrupadas bajo un mismo nombre para hacer mas eficiente elmanejo. Las estructuras se denominan registros en otros lenguajes; por ejemplo,en Pascal.

• Opcionalmente puede seguir un nombre a la palabra clave struct; se lo denom-ina nombre de la estructura y se puede emplear en declaraciones posteriorescomo una abreviatura de la estructura.

• La llave de cierre que termina la lista de miembros puede ir seguida de unalista de variables.

• Si la declaracion de una estructura no va seguida de la lista de variables, nose reserva memoria alguna; en este caso se esta describiendo una plantilla dela estructura.

• Se puede inicializar una estructura externa o estatica anadiendo a su defini-cion la lista de inicializadores de los componentes.

• Las estructuras se pueden anidar.

• Podemos declarar arrays de estructuras.

Acceso. Para referenciar un miembro de una estructura en una expresion, seemplea la notacion punto.

nombre_de_la_estructura.miembro

4.12.5. Restricciones de las estructuras

Las estructuras no pueden compararse; las unicas operaciones que se pueden realizarcon una estructura son copiarlas o asignarlas como un todo, tomar su direccion (me-diante &), y acceder a uno de sus miembros.

Page 18: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 17

4.12.6. Union

Una union es una estructura donde todos los miembros tienen desplazamiento cero. Laestructura es lo suficientemente grande como para contener el mayor de los miembros,y la alineacion es la apropiada para todos los tipos de la union. Es responsabilidad delprogramador recordar cual es el tipo que hay en la union. Las uniones pueden aparecerdentro de estructuras y arreglos, o viceversa. La notacion para acceder a un miembrode una union dentro de una estructura (o viceversa) es identica a la empleada conestructuras anidadas.

4.12.7. Campos de bit

La forma usual de manejar bits consiste en definir un conjunto de mascaras (en poten-cias de 2) que corresponden a las posiciones de los bits. El acceso a los bits se convierteen un juego de operaciones de desplazamiento, enmascaramiento y complementacion.

C posee capacidad para definir y acceder directamente a campos definidos en el interiorde una palabra, en lugar de hacerlo mediante mascaras. Un campo es un conjunto debits adyacentes dentro de un int. La sintaxis de la definicion de los campos se basa enlas estructuras. Los campos sin nombre (dos puntos y un tamano solamente) sirven derelleno.

Page 19: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 18

4.13. Punteros

Un puntero es una variable que contiene la direccion de otra variable. Los punteros seutilizan con abundancia en C, debido a que:

A veces son la unica manera de expresar un calculo.

Con ellos puede obtenerse un codigo mas compacto y eficiente.

C proporciona dos operadores especiales para punteros:

El operador unitario * toma su operando como una direccion y accede a ella paraobtener su contenido.

El operador unitario & devuelve la direccion de un objeto. Solo puede aplicarsea variables y a elementos de un arreglo; construcciones como &(x + 1) y &3 sonilegales. Tambien es ilegal obtener la direccion de una variable de tipo register.

La declaracion del puntero p1 se entiende como un nemotecnico; se quiere indicar quela combinacion ∗p1 equivale a una variable de tipo int. C permite declarar punterosdobles (punteros a punteros).

En general, un puntero se puede inicializar como cualquier otra variable, aunque nor-malmente los unicos valores significativos son cero (NULL) o una expresion en queaparezcan direcciones de objetos del tipo apropiado.

Los punteros pueden aparecer en expresiones. Los operadores unitarios ∗ y & tienenmayor precedencia que los operadores aritmeticos, por lo que al evaluar y = ∗p1 + 1la expresion toma el valor del objeto al que apunta p1, se le suma 1, y el resultado seasigna a y. Tambien pueden aparecer referencias a punteros en la parte izquierda deuna asignacion (∗p1 = 0; ∗p1+ = 1).

La expresion (∗p1) + + necesita los parentesis; sin ellos incrementarıa el valor delpuntero p1 y no el objeto al que apunta, ya que los operadores unitarios ∗ y ++ seevaluan de derecha a izquierda.

Los punteros se pueden comparar entre ellos o con cero (NULL).

Como los punteros son variables, se pueden manipular igual que cualquier otra variable(p2 = p1).

Como los parametros de las funciones se pasan siempre por valor, cuando queremosque la funcion devuelva valores mediante los parametros tenemos que pasar punteros.

Page 20: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 19

4.13.1. Punteros y arrays

En C existe una estrecha relacion entre punteros y arrays, ya que cualquier operacionque se pueda realizar mediante la indexacion de un array se puede realizar tambien conpunteros. La version con estos puede ser mas rapida pero, mas difıcil de entender.

Si ptr apunta a un elemento particular de un array, entonces ptr− i apunta al elementoque esta i elementos antes de ptr, y ptr + i apunta al elemento que esta i elementosdespues. Si ptr apunta a a[0], entonces ∗(p1 + i) se refiere al contenido de a[i]. Esto escierto independientemente del tipo de variables del array. La definicion de sumar 1 aun puntero, y, por extension, toda la aritmetica de punteros establece que el incrementose adecua al tamano en memoria del objeto apuntado. En pa + i, i se multiplica por eltamano de los objetos a los que apunta pa antes de ser sumado a p1.

Cuando se pasa el nombre de un array a una funcion, se pasa la direccion del comienzodel array (un puntero). El paso de arrays multidimensionales a una funcion no requiereespecificar la primera dimension (es irrelevante porque lo que se trasmite realmente es,como antes, un puntero). En el ejemplo de la transparencia, la ultima declaracion de laderecha indica que el parametro es un puntero a un array de 4 enteros. Los parentesisson necesarios porque los corchetes [ ] tienen mayor precedencia que el operador ∗; sinparentesis. La declaracion int *tabla[4]; serıa un array de 4 punteros a enteros.

4.13.2. Punteros y estructuras: notacion − >

Si p es un apuntador a una estructura, los miembros de la estructura se pueden ref-erenciar mediante (*pd).miembro (hacen falta los parentesis porque la precedencia deloperador de miembro de estructuras es mayor que la de *). Sin embargo, como son tanfrecuentes los apuntadores a estructuras se ha introducido en el lenguaje la notacionabreviada − >, que es equivalente.

4.13.3. Punteros a funciones

En C es posible definir un puntero a una funcion, que puede ser manipulado, pasadoa funciones, colocado en arrays, etc. La declaracion de un puntero a funcion tiene lasiguiente sintaxis:

tipo (*nombre_puntero)()

Es necesaria la primera pareja de parentesis. Sin ellos estarıamos haciendo una declaracionde una funcion que devuelve un puntero a un entero. La llamada se realiza mediante:

(*nombre_puntero)(parametros)

Page 21: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 20

4.13.4. Resumen de aritmetica de punteros

En resumen, las operaciones aritmeticas que podemos realizar con los punteros de Cson las siguientes:

Pueden inicializar como cualquier otra variable, aunque normalmente los unicosvalores significativos son 0 (NULL) o una expresion en que aparezcan direccionesde objetos del tipo apropiado.

Puede sumarse o restarse un entero a un puntero.

Pueden compararse.

Pueden restarse punteros.

No se permite sumar, restar, multiplicar, dividir, rotar, enmascararpunteros, ni sumarles valores float o double.

Page 22: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 21

4.13.5. Parametros de la lınea de comandos

Cuando se invoca main al comienzo de la ejecucion, se llama con dos parametros.

1. El primero (llamado argc por convenio) es el numero de argumentos en la lıneade comandos con que se invoco al programa.

2. El segundo (argv) es un puntero a un array de cadenas de caracteres que contienenlos argumentos, uno por cadena.

Por convenio, argv[0] es el nombre con el que se invoco el programa; por tanto, argc escomo mınimo 1 (el primer argumento real es argv[1] y el ultimo es argv[argc-1]).

Debido a que argv un puntero a un array de punteros, existen varias maneras demanipular los parametros.

Page 23: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 22

4.14. Tratamiento de ficheros

Para manejar ficheros con formato en C necesitamos punteros a una estructura de datisdefinida en el fichero <stdio.h> denominada FILE. Las principales funciones C paratratamiento de ficheros son:

1. Apertura, cierre, renombrado y borrado:

FILE *fopen(char *nombre, char *modo)El modo de apertura puede ser:

• r: modo lectura.

• w: modo escritura (crea el fichero si no existe y descarta su contenido encaso de que ya existiese).

• a: modo anadir (si no existe lo crea).

Los modos r+, w+ y a+ tienen el mismo significado que sus homologos r, w,a, pero se permite tanto la lectura como la escritura. Si el modo incluye unab (rb, r+b), significa que es un fichero binario. En caso de error retorna unpuntero NULL.

int fclose(FILE *f)

int rename(const char *antiguo nombre, const char *nuevo nombre)

int remove(const char *nombre fichero)

2. Transferencia:

int fgetc(FILE *f)

int fputc(int c, FILE *f)

char *fgets(char *linea, int max linea, FILE *f)

int fputs(char *linea, FILE *fp)

int fscanf(FILE *f, char *format, ....)

int fprintf(FILE *f, char *format, ....)

3. Posicionamiento:

int fseek(FILE *f, long despl, int posicion)

long ftell(FILE *f)

void rewind(FILE *f);

4. Funciones de error:

int ferror(FILE *f)

int feof(FILE *f)

Existen tres punteros de tipo FILE que son estandar y estan definidos en <stdio.h>:stdin, puntero a la entrada estandar, stdout, puntero a la salida estandar y stderr,puntero a la salida estandar de errores. Las funciones getchar() y putchar() son macrosdefinidas en <stdio.h> de la siguiente forma:

#define getchar() getc(stdin)

#define putchar(x) putc(x,stdout)

Page 24: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 23

4.15. Errores frecuentes de los programadores de C

En este ultimo apartado se presentan los errores que comenten con mas frecuencia losnuevos programadores de C.

Page 25: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 24

Page 26: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 25

Page 27: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 26

Page 28: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 27

4.16. Programacion de estructuras de datos dinamicas con C

La combinacion de estructuras (registros) y punteros permiten crear estructuras cuyaforma y tamano no sea fija: estructuras de datos dinamicas. La unidad basica de lasestructuras dinamicas es el nodo (registros que son enlazados mediante punteros paraformar la estructura deseada). En terminos generales las estructuras se pueden agruparen tres clases: estructuras lineales, estructuras jerarquicas, y grafos3.

La declaracion de un nodo se realiza mediante una declaracion recursiva (una estructuraque se autoreferencia —ver transparencia—). El miembro next es una variable de tipopuntero que contendra la direccion de otro nodo.

Para utilizar las estructuras dinamicas es necesario solicitar memoria (mediante mal-loc()) y liberar memoria (mediante free()). Para ello es necesario utilizar las rutinasdefinidas en el fichero stdio.h.

En las siguientes transparencias veremos como podemos implementar en C las sigu-ientes estructuras dinamicas:

Pilas.

Colas.

Listas simplemente encadenadas.

Listas doblemente encadenadas.

Arboles.

3Un grafo es una generalizacion de una estructura dinamica en la que cada nodo puede tener varios enlaces,

y pueden existir bucles

Page 29: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 28

4.16.1. Pila (LIFO)

Una pila es una estructura de datos que consta de dos operaciones: push() para insertarun elemento y pop() para extraer el ultimo elemento insertado. Por esta razon las pilastambien se denominan estructuras LIFO (del ingles Last In First Out).

Las pilas pueden declararse mediante arrays. Esto tiene el inconveniente de que necesi-tamos reservar el espacio maximo necesario para ella. En la transparencia se presentala implementacion en C de una pila dinamica de datos de tipo entero. Utilizamos lavariable global Top para apuntar a la cima de la pila. El algoritmo de las funcionespush() y pop() es el siguiente:

Push():

• Creamos un nuevo nodo.

• Rellenamos la informacion del nuevo nodo.

• Actualizamos el puntero de cima de pila al nuevo nodo.

Pop():

• Si la pila esta vacıa retornamos un codigo de error.

• Guardamos en una variable auxiliar la informacion del nodo que esta en lacima de la pila.

• Guardamos en un puntero auxiliar la direccion del nodo que esta en la cimade la pila.

• Actualizamos el puntero de cima de pila al siguiente nodo.

• Liberamos el nodo que estaba en la cima de la pila.

• Retornamos la informacion que contenıa el nodo que hemos liberado.

Page 30: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 29

4.16.2. Cola

Una cola es una estructura de datos que consta de dos operaciones: una para insertarun elemento al final de la cola y otra para para extraer el elemento que esta al principiode la cola. Por esta razon las pilas tambien se denominan estructuras FIFO (del inglesFirst In First Out).

En esta implementacion utilizamos las variables globales principio y final para apuntaral primer y ultimo elemento de la cola. El algoritmo de las funciones insertar() yextraer() es el siguiente:

Insertar()

• Creamos un nuevo nodo.

• Rellenamos la informacion del nuevo nodo.

• Si la cola esta vacıa actualizamos los punteros primero y siguiente al nuevonodo.

• Si la cola no esta vacıa insertamos el nuevo nodo al final de la cola.

Extraer()

• Si la cola esta vacıa retornamos un error.

• Guardamos en variables auxiliares la informacion del primer elemento de lacola (el nodo que vamos a liberar) y la direccion del segundo elemento de lacola (que va a pasar a ser el nuevo primer elemento de la cola).

• Liberamos la memoria del primer elemento.

• Actualizamos el puntero al nuevo primer elemento de la cola.

• Si la cola esta vacıa (el primer elemento es NULL), actualizamos el punteroal ultimo elemento de la cola a NULL.

• Retornamos la informacion del nodo que hemos extraido.

Page 31: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 30

4.16.3. Lista simplemente encadenada

La implementacion de una lista simplemente encadenada es similar a cola, pero sediferencia en que los elementos se insertan y extraen de forma ordenada.

Page 32: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 31.

Lista simplemente encadenada (cont.)

La funcion de busqueda recibe un parametro de entrada (el dato a buscar —n—) yretorna dos parametros de salida:

1. El nombre de la funcion retorna un puntero al nodo donde se encontro el dato.

2. El parametro de salida anterior es un puntero al nodo que hay antes (siguiendoel orden de la lista) del nodo donde se encontro el dato.

De esta forma podemos utilizar la funcion buscar con dos fines:

1. Saber la informacion solicitada esta en la lista (ya que la funcion retorna NULLcuando la clave no esta en la lista).

2. Facilitar la extraccion del nodo (ya que la funcion retorna las direcciones del nodoanterior al buscado y la direccion del nodo buscado, con lo que solamente necesita-mos actualizar los punteros —observese la funcion Borrar en la transparencia—).Si anterior vale NULL significa que la clave se encontro en el primer nodo de lalista.

Page 33: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 32

4.16.4. Lista doblemente encadenada

En una lista doblemente encadenada cada nodo tiene dos punteros: un puntero alsiguiente nodo (en orden) de la lista, y un puntero al nodo anterior. Como puedeapreciarse en la transparencia, la funcion de insercion es similar a la funcion de insercionen una lista simplemente encadenada (solo hay que tener cuidado en la actualizaciondel nuevo puntero).

Page 34: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 33

4.16.5. Arbol binario

El arbol binario es probablemente la estructura dinamica mas utilizada. Cada nodode la estructura tiene un predecesor (padre o ancestro) y uno o dos sucesores (hijo odescendientes).

La transparencia contiene el pseudocodigo de un algoritmo de recorrido in-order iter-ativo del arbol binario. El algoritmo consiste en comenzar profundizando en el arbolsolamente por la rama izquierda de los nodos a la vez que almacenamos en la pila ladireccion de estos nodos (porque aun no los hemos procesado).

Al llegar a lo mas profundo del a’rbol por su rama mas izquierda, en la cima de lapila tenemos el primer nodo que debemos procesar. Por lo tanto, extraemos el nodode la pila, lo procesamos, e intentamos profundizar a partir de su hijo derecho. Si notiene hijo derecho, sacamos otro nodo de la pila (el padre), lo procesamos e intentamosprofundizar por su hijo derecho. Este proceso se repite hasta procesar el arbol completo.

El algoritmo recursivo es quizas mas facil de entender. Es basicamente el mismo al-gorimo, lo que en este caso la pila se implementa de forma automatica mediante lasllamadas recursivas.

Page 35: El lenguaje de programaci on C (Explicaci on de las ... · El lenguaje de programaci on C ... En 1969 Thompson intenta utilizar FORTRAN para escribir ... [Gehani, 89], C* [Thinking,

El lenguaje C

18 de febrero de 2004Notas 34.

Arbol binario (cont.)

La insercion en el arbol binario sigue el siguiente algoritmo:

Si el arbol esta vacıo, la raiz es el nuevo nodo que ibamos a insertar.

Si el arbol no esta vacıo, buscamos la posicion en el arbol donde debemos insertarel nodo y actualizar el puntero correspondiente.