Está en la página 1de 107

Lenguaje C

Copyleft (c) 2006, Jose Daniel Gutiérrez Porset


josedaniel.gutierrez@ehu.es
Licencia de Uso

Acerca de este documento

Copyright (c) 2006, Jose Daniel Gutiérrez Porset


josedaniel.gutierrez@ehu.es

Se otorga permiso para copiar, distribuir y/o modificar este


documento bajo los términos de la Licencia de Documentación Libre
de GNU en su versión 1.2 o cualquier otra versión posterior publicada
por la Free Software Foundation, siendo todo él invariante. Una copia
de la licencia está disponible en la web de la Free Software
Foundation, dentro de la sección titulada GNU Free Documentation
License.

Este documento ha sido realizado íntegramente con software libre.

2
Índice


Licencia de uso de este documento

Introducción al lenguaje C

El preprocesador

Variables, constantes y literales

Expresiones y Operadores

Punteros

Control de flujo

Funciones

Arrays

Cadenas de caracteres

Estructuras

Tipos combinados

Gestión de memoria dinámica

Ficheros y streams
3
Introducción al lenguaje C
Características generales

Lenguaje compilado

Lenguaje de nivel medio­bajo

“case­sensitive”

Especificaciones:
– K&R (Dennis Ritchie and Brian Kernighan)
– ANSI C (X3.159­1989) e ISO C
– C99

Más información en:
http://en.wikipedia.org/wiki/C_programming_language

4
Introducción al lenguaje C
Fases
vim, emacs, eclipse
1. Edición Editor
nano, kate, gedit,...

Fuente
.h,.c
Precompilador
2. Precompilación cpp
Fuente
precompilado

3. Compilación Compilador
gcc
Fuente GNU/Linux: .o
compilado Ms: .obj
4. Enlazamiento o Linkado

Librerías Enlazador
Librería 1 ld
Librería 1 Ejecutable Ms: .exe
GNU/Linux: .a,.la,.so
5
Ms: .lib
Introducción al lenguaje C
Edición de ficheros fuente

Claridad y facilidad de lectura:
– Usar indentaciones
– Dejar espacios
– Ejemplos de malas prácticas:
http://www.es.ioccc.org/main.html

Sintaxis de estructura correcta. Palabras reservadas.

Tipos de errores y avisos:
– Error de compilación: el compilador indica un error y no llega a 
compilar el fuente
– Warning: el compilador compila el fuente pero avisa de algo.
– Error de ejecución
– Errores de funcionalidad y/o diseño 6
Introducción al lenguaje C
Estructura de un fichero fuente .c

int main (void)

7
Introducción al lenguaje C
Tipo de líneas de un fichero fuente .c

Instrucciones de precompilador: #

Comentarios
– 1 sola línea: //
– Más de 1 línea: entre /* y */

Sentencias simples acabadas en ;

Líneas no acabadas en ; (ej. sentencias if de una línea).

Bloques de sentencias entre { y }

Líneas vacías

8
Introducción al lenguaje C
Estructura de un fichero cabecera .h

Símbolos y macros de preprocesador

Declaraciones de estructuras, uniones y enumeraciones

Declaraciones typedef

Declaraciones de funciones externas

Declaraciones de variables globales

9
El preprocesador
Introducción

Preprocesador = Precompilador 

Usos:
– Incluir ficheros externos en compilación.
– Definir y reemplazar etiquetas y macros.
– Realizar compilaciones condicionales.
Ej. un único fuente compilable para más de un sistema operativo

10
El preprocesador
Sintaxis

Sintaxis: líneas comienzan por #
Uso Sintaxis
Inclusión de ficheros #include < >
externos #include “ “
Definición de símbolos y #define
macros #undef
Condiciones #ifdef
#ifndef
#if expresión
#elif expresión
#else
#endif
Operadores para #if y #elif defined && ||


Algunos símbolos definidos: __DATE__, __FILE__, 
__LINE__, __TIME__
11
Sistemas numéricos
y de caracteres
Sistemas numéricos

Conceptos:
– Conjunto de símbolos=base
– Tamaño de palabra.
– Rango de valores representables en un sistema de base B con N 
símbolos:

Se pueden formar BN palabras

Los valores van de 0 a BN­1

Desbordamientos u overflow.

12
Sistemas numéricos
y de caracteres
Sistemas numéricos

Bases más empleadas:
– Personas: decimal (base 10)
– Ordenadores:

binario (2): 0, 1. Bit y byte. Valores negativos: en C complemento a 2 
(“rueda”, ej. 100 binario =­4 decimal, 111 binario=­1 decimal)

hexadecimal (16): 0,1,...,9,A,B,C,D,E,F

octal (8): 0, 1,...,7

Conversión entre sistemas (base 10 a binario y viceversa).

13
Sistemas numéricos
y de caracteres
Equivalencias

1 byte = 8 bits

1 K = 1024

1 M = 1024 K

1 G = 1024 M

14
Sistemas numéricos
y de caracteres
Tabla ASCII de caracteres

Representación de 128 caracteres con 7 bits.
– 33 no imprimibles
– 95 imprimibles. Ej. '0'=48,'A'=65. 
!"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~
– No están ej. acentos ñ º ª

Dualidad carácter – número y uso de tipo char

15
Variables, Constantes y
Literales
Variables y Constantes

Variables y constantes: son representaciones de una 
dirección de memoria en la que se guardará un dato o 
conjunto de datos de un tipo concreto.

Conceptos básicos:
– Dirección de memoria.
– Valor. Valor inicial. Cambio en tiempo de ejecución.
– Ámbito de acceso o zona del programa de validez.

16
Variables, Constantes y
Literales
Declaración de variables y constantes

Concepto de declaración:
– Se reserva de espacio en memoria para almacenar el valor o 
valores que representa.
– Especificación del ámbito y el tipo.

Es obligatorio antes del uso.

Si son variables locales a una función, se suelen declarar al 
principio de la misma (aunque no es estrictamente 
obligatorio).

17
Variables, Constantes y
Literales
Declaración de variables y constantes

Sintaxis para la declaración:
[<modificador>] <tipo_dato> <nombre_var>;
o bien:
<tipo_dato> [<modificador>] <nombre_var>;

Elementos:

18
Variables, Constantes y
Literales
Identificadores

Identificador o nombre

Normas para identificadores:
– 1er carácter: sólo ‘A’,…,’Z’, ’a’,…, ’z’, ‘_’, (‘$’ según versiones)
– Resto de caracteres: ‘A’,…,’Z’, ’a’,…, ’z’, ‘0’,..., ‘9’, ‘_’, (‘$’ según 
versiones)
– No se permiten palabras clave de C

Por convenio (no obligatorio):
– Las variables se escriben en minúsculas
– Las constantes se escriben en mayúsculas
– Si constan de varias palabras, van separadas por _

19
Variables, Constantes y
Literales
Tipos

El tipo de un dato especifica:
– La naturaleza o uso de los datos que representa
– El nº de bytes que ocupa en memoria
– El rango de valores que puede contener

Los tipos de datos pueden ser:
– Predefinidos o propios del lenguaje C
– Combinados a partir de los definidos
– Definidos por quien programa

20
Variables, Constantes y
Literales
Tipos de datos predefinidos en C

Números enteros
Palabra clave Tamaño (bytes) Rango
char 1 [-128, 127]
unsigned char 1 [0,255]
short 2 (>=2 según S.O.) [-32.768, 32.767]
unsigned short 2 (>=2 según S.O.) [0, 65.535]
int 4 (>=2 según S.O.) [-2.147.438.648, 2.147.438.647]
unsigned int 4 (>=2 según S.O.) [0, 232-1]
long 4 (>=4 según S.O.) [-2.147.438.648, 2.147.438.647]
unsigned long 4 (>=4 según S.O.) [0, 232-1]


Números reales
Palabra Tamaño Rango
clave (bytes)
float 4 [-3,4 * 1038, -1,18 * 10-38] 0 [1,18 * 10-38, 3,4 * 1038]
double 8 [-1,79 * 10308, -2,23 *10-308] 0 [1,79 * 10-308, 2,23 * 10308]
long double 12

(Para ver los rangos, mirar /usr/include/limits.h) 21
Variables, Constantes y
Literales
Tipos de datos predefinidos en C

Otros
Palabra clave Tamaño (bytes)
struct depende
union depende
[] depende
* 4 (según S.O.)
(bitfields) depende
enum depende

– Nota: void no representa un tipo como tal pero aplica a:

Funciones que no devuelven nada

Argumento para funciones que no tienen parámetros

Punteros

22
Variables, Constantes y
Literales
Modificadores

Elemento sintáctico para indicar características como:
– Ámbito. Si no se indica nada, en una declaración dentro de una 
función indica ámbito local, y fuera de una función indica ámbito 
global.
– Si es constante o variable. Si no se indica nada es variable (no 
constante)

23
Variables, Constantes y
Literales
(Modificadores)

const:
– El valor es una constante en tiempo de ejecución
– Ámbito: idem que lo indicado

static
– En una declaración dentro de una función indica ámbito local, y:

El valor se mantiene entre llamadas a la función.

El valor se inicializa a 0.
– En una declaración fuera de una función, indica ámbito de 
módulo.

extern: Se emplea para referenciar a variables y constantes 
globales declaradas en otro fichero.
24
Variables, Constantes y
Literales
Clasificación de variables

Variables y Constantes locales
– Ámbito: la función en la que se declaran
– Valor inicial: si se usa static 0 y si no indeterminado

Parámetros de una función
– Ámbito: la función en la que se declaran
– Valor inicial: el valor de la llamada

25
Variables, Constantes y
Literales
(Clasificación de variables)

Variables y Constantes de módulo o fichero fuente
– Ámbito: el fichero fuente
– Valor inicial: 0

Variables y Constantes globales
– Ámbito: todo el programa, incluso distintos módulos
– Valor inicial: 0

26
Variables, Constantes y
Literales
Asignación de variables

Concepto de Asignación: dar un valor a la variable.

Sintaxis para la asignación:
<nombre_var> = <valor>;

La primera vez que se asigna un valor se llama 
“inicialización”. Hasta ese momento el valor de la variable 
es indeterminado.

Puede inicializarse en la declaración. Sintaxis para la 
declaración con inicialización:
[<modificador>] <tipo_dato> <nombre_var> = <valor>;

27
Variables, Constantes y
Literales
Constantes

No cambian de valor en tiempo de ejecución

Definición de constantes:
– En el preprocesador, mediante #define
– En el compilador, declarando una variable con el modificador 
const. Es obligatorio inicializarlas en la declaración. Ej:
int const PI=3.14;

28
Variables, Constantes y
Literales
Literales

Son las apariciones de números, caracteres y cadenas de 
caracteres.
Constante Representación Tipo Ejs
Números -Formato decimal int o 3
enteros -Formato octal: 0nn siendo nn cifras de 0 a 7 long ('L') 5L
-Formato hexadecimal: 0xnnnn... siendo nnnn...: 047
0,...,9,a,...,f,A,...,F 067L
0xA4
0x123L
Números -Formato decimal: M.N double o 3.0
reales -Formato exponencial (equivalente a Mx 10N): float (‘f’ o 45.6F
MeN ‘F’). 2.4e3f
Caracteres Valor entre comillas simples char 'a'
Caracteres no imprimibles: Secuencias de Escape '\t'
Cadenas Valor entre comillas dobles “\nKaixo\tama”
de Internamente terminan en '\0'
caracteres Caracteres no imprimibles: Secuencias de Escape

29
Variables, Constantes y
Literales
Literales – secuencias de escape

Las secuencias de escape son literales formados por parejas 
de caracteres donde el primer carácter es \ que tienen un 
significado especial.
Secuencia de Escape Carácter
\" "

\' '

\? ?

\\ \

\a BEL (timbre)

\b BS (backspace)

\f FF (form feed)

\n NL (newline)

\r CR (Carriage Return)

\t HT ( Horizontal Tab)

\v VT (Vertical Tab)

\0 NULL
30
Funciones básicas de E/S


(Más adelante se verán las funciones en profundidad)

Funciones: E S Comentarios
scanf printf Según formato
getchar putchar Carácter
gets puts Cadena


Necesario:
    #include <stdio.h>

31
Funciones básicas de E/S


Cadenas de formato para printf y scanf:
Tipo Cadena Comentarios
char "%c” Con printf muestra el carácter del código ASCII
correspondiente

int “%d” o “%i” Con printf de char muestra el valor numérico del
código ASCII

long “%li”

float y double “%f”

Cadena “%s”

Puntero “%p”


Uso de & en scanf:
– Sí para leer variables de tipo número o carácter
– No para leer contenidos de arrays o cadenas y se hace con el 
nombre del array o la cadena
32
Funciones básicas de E/S
Precauciones

En funciones con formato (printf, scanf) hacer 
corresponder el nº y tipo de parámetros al nº y tipos 
indicados con %

En scanf usar adecuadamente &

33
Expresiones y Operadores
Introducción

Expresiones: combinación de operadores y operandos.

Operadores: indican la operación a realizar para evaluar un 
valor.

Operandos: variables y constantes

Conversión de tipos de datos: implícita y explícita

34
Expresiones y Operadores
Clasificación de operadores
Grupo Nº args
Aritméticos unarios expr++ expr-- ++expr --expr + -

binarios + - * / %

Aritméticos bits unarios ~


binarios >> << & | ^
Lógicos unarios !
binarios > < >= <= == !=
&& ||
ternarios ?:
Asignación binarios = += -= *= /= %=

Asignación bits binarios >>= <<= &= |= ^=

Memoria unarios * &


binarios . -> []
Otros unarios () (casting) sizeof
binarios ,

35
Expresiones y Operadores
Operador sizeof

Indica el tamaño en bytes ocupado por el operando, que 
puede ser:
– una variable
– una constante literal
– una constante en tiempo de ejecución
– un tipo de dato; es obligatorio que el tipo esté entre ( )

36
Expresiones y Operadores
Comentarios a operadores

% sólo opera entre números enteros

Operadores lógicos:
– Dan como resultado numérico 1 si es verdadero y 0 si es falso 
es.
– El operador ! aplicado a números da 1 si el argumento es 
distinto de 0 y 0 en caso contrario. Equivale a arg!=0

() puede tener 3 usos: función, agrupación y casting.

Operador coma ,: se usa para separar expresiones y el resultado 
es la última expresión. Poco empleado.

37
Expresiones y Operadores
Precauciones

No confundir = con ==. El operador = siempre devuelve 
el valor de la asignación.

Cuidado con la precisión y los overflows o 
desbordamientos. Especialmente en el operador casting

38
Expresiones y Operadores
Tabla de precedencia
Grupo Operador Dirección

Expresiones varias () [] . -> expr++ expr-- izda-a-dcha


* & + - ! ~ ++expr --expr
Operadores unarios (typecast) sizeof() dcha-a-izda
Operadores binarios */% izda-a-dcha
+-
>> <<
< > <= >=
== !=
&
^
|
&&
||
Operador ternario ?: dcha-a-izda
= += -= *= /= %= >>= <<= &=
Asignación ^= |= dcha-a-izda
Coma , izda-a-dcha

39
Punteros
Concepto

Conceptos: dirección y contenido

En una dirección de memoria puede haber uno de estos 
contenidos:
– Datos: variables y constantes en tiempo de ejecución
– Código: funciones

Puntero: tipo de dato que representa una dirección de 
memoria en la cual se almacena un dato o bien se 
encuentra una función

40
Punteros
Declaración

Se reserva memoria para almacenar una dirección (4 
bytes).

Sintaxis para la declaración:
<tipo_apuntado> * <nombre_var_puntero>;

Si <tipo_apuntado> es void, el puntero puede usarse para 
apuntar a una función, o para apuntar a cualquier tipo de 
dato.

41
Punteros
Operador *

Usos:
– (Multiplicación)
– Declaración de puntero.
– Contenido de una dirección de memoria. El operando puede ser:

Una variable de tipo puntero

Una constante en tiempo de ejecución de tipo puntero

Un número entero (esté en una variable, constante en tiempo de 
ejecución, o sea un literal) al que se hace un casting a puntero.

42
Punteros
Operador &

Usos:
– (and lógico de bits)
– Dirección de memoria (donde hay una variable,...). El operando 
puede ser:

Una variable

Una constante en tiempo de ejecución

Una función

(Nunca un literal)

Ejemplo: uso en función scanf

43
Punteros
Operadores aritméticos, de comparación y asignación

Operadores aritméticos +, ­, ++, ­­: tienen en cuenta el 
tipo apuntado.

Operadores de comparación (==,!=) entre punteros:
– Comparan las direcciones de los punteros, pero no el contenido.

Operador de asignación (=) entre punteros:
– Copia una dirección en la otra, no los contenidos.

44
Punteros
Precauciones

Acceso indebido a memoria: no se debe acceder a zonas de 
memoria no declaradas por el programa
– Puede ocasionar errores graves en lectura, y muy graves en 
escritura.
– No es un error detectado en tiempo de compilación

Saber cuándo hay que usar &,  * o ninguno de los 
anteriores

45
Control de Flujo
Clasificación de sentencias

Condicionales: ejecutan una sola vez una o varias líneas de 
código dependiendo de una condición
– if
– switch

Repetitivas: ejecutan varias veces una o varias líneas de 
código dependiendo de una condición
– while
– do – while
– for

46
Control de Flujo
Sentencia if

Sintaxis:
if (<expresión>) {
<bloque sentencias ok>
} [else {
<bloque sentencias no ok>
}]

47
Control de Flujo
Sentencia switch

Sintaxis:
switch (<expresión>) {
case <constante 1>:
[<bloque sentencias 1>
[break;]]
case <constante 2>:
[<bloque sentencias 2>
[break;]]
...
case <constante n>:
[<bloque sentencias n>
[break;]]
[default:
<bloque sentencias default>]
}

– Si no se indica break, se ejecuta el siguiente bloque siempre, 
48
aunque no se cumpla su condición case
Control de Flujo
Sentencias while y do-while

Sintaxis while:
while (<expresión>) {
<bloque sentencias ok>
}


Sintaxis do while:
do {
<bloque sentencias>
} while (<expresión>);

49
Control de Flujo
Sentencia for

Sintaxis:
for ([<inicialización>];[<expresión>];[<actualización>])
{
<bloque sentencias>
}


Funcionamiento:
– 1) <inicialización>
– 2) La expresión se evalúa a verdadero o falso
– 3.a) Si <expresión> es verdadera se ejecuta el bloque, después se 
ejecuta <actualización> y finalmente se vuelve a 2)
– 3.b) Si <expresión> es falsa se termina
50
Control de Flujo
Resumen y Comentarios

Uso de <expresión>
– En if, while, do while, for: se evalúa a verdadero o falso
– En switch: se compara con constantes enteras

En if, while, do while, for si <bloque de sentencias> tiene 
sólo 1 línea no es necesario encerrarlo entre { }, e incluso 
se puede escribir todo en una línea.

Claridad en la escritura:
– Indentación
– Distintos lugares posibles de { }

Posibilidad de anidamientos.

51
Control de Flujo
Precauciones

Bucles infinitos para las sentencias repetitivas

Si <bloque de sentencias> tiene más de 1 línea:
– En if, while, do while, for es obligatorio el uso de { }
– En switch no es obligatorio lo anterior

Anidamientos: ojo a indentaciones, else, {} y ;

if y while no llevan ; después de la condición, a no ser que 
se ponga a propósito por algo

Casos especiales de expresiones condicionales:
– Si no es una expresión de comparación
– Uso de = en vez de ==
52
Funciones
Introducción

Filosofía de programación modular:
– Dividir problema complejo en problemas sencillos
– Razones:

Claridad

Facilidad de desarrollo

Facilidad de mantenimiento: detección de errores, modificaciones,...

53
Funciones
Conceptos

Función: Bloque de sentencias que realizan una tarea de 
mayor o menor nivel (=más general o más concreta)

Función que hace la llamada y función que es llamada

Llamada una o, en general, más veces

Resultado

Parámetros o argumentos:
– Formales: los de la declaración.
– Reales: los valores concretos pasados en tiempo de ejecución.

54
Funciones
Introducción

En C:
– Puede recibir o no parámetros concretos en cada llamada
– Puede devolver uno o ningún resultado
– Puede modificar los valores originales de los parámetros que recibe
– En un fichero fuente no puede haber más de una función con un 
mismo nombre
– Función especial: main

3 Sentencias de funciones:
– Declaración, Definición, Llamada

55
Funciones
Declaración de Funciones

Concepto: indicar al compilador y al enlazador:
– El nombre de la función
– El tipo de dato que devuelve
– El nº y tipo de parámetros
– (El ámbito:)

static: local al fichero fuente; el nombre no se exporta al linker

extern: el código está en otro fichero

Sinónimo: prototipo.

56
Funciones
Declaración de Funciones

Sintaxis:
<tipo> <nombre funcion> ([lista de parámetros]);
– <tipo>: si no devuelve nada, se indica void
– <lista de parámetros>:

Tipos y, opcionalmente nombres (útil a nivel descriptivo, ej. caso de 
funciones de librerías), separados por comas.

Si no recibe ningún parámetro, se puede indicar void

Lugar para la declaración: antes de ser llamadas
– Las funciones definidas por el usuario van antes del main
– Las funciones no definidas por el usuario (ej. las del sistema, otras 
librerías,...) van en un fichero .h.

57
Funciones
Definición de Funciones

Concepto: programación del código o implementación

Sintaxis:
<tipo> <nombre funcion> ([lista de tipos y nombres
de parámetros])
{
[<declaración de variables locales a la
función>]
[<sentencias de la función>]
[return <expresión>;]
}

58
Funciones
Definición de Funciones

Comentarios:
– Primera línea semejante a la declaración. Diferencias:

No termina en ;

Además de los tipos ha de incluir los nombres de los parámetros

Lugar de la definición: suelen ir en el mismo fichero 
después del main, pero podrían estar:
– En un fichero fuente .c aparte.
– En un fichero ya compilado (objeto o librería), ej. printf

59
Funciones
Llamadas a Funciones

Concepto: salto a la primera línea del código de la función

Sintaxis:
... <nombre funcion> ([lista de valores de
parámetros]) ...

<lista de valores de parámetros>

– Separados por comas.
– Los valores reales en el momento de la llamada
– Pueden ser:

Variables

Expresiones de variables y/o constantes

60
Funciones
Llamadas a Funciones

Lugares de la llamada: puede llamarse una o varias veces 
en el programa, siempre desde una función que puede ser:
– La main
– Otra función
– La misma función: recursividad

61
Funciones
Contextos

Contexto = ámbito = zona del programa donde unas 
variables tienen sentido

Se distinguen:
– Contexto de la función desde la que se hace la llamada
– Contexto de la función llamada

Los parámetros pasados a una función existen en ambos 
contextos:
– En el de la función desde la que se llama y a la que se vuelve. 
Pueden ser:

Variables

Expresiones de variables y/o constantes
– En el de la función llamada. Son idénticos a las variables locales 62
Funciones
Paso de parámetros

En el caso de que un parámetro sea una variable (no una 
expresión de variables y/o constantes), al volver al 
contexto de la función desde la que se llamó pueden ocurrir 
dos casos:
– Que  el valor de la variable no se haya modificado en la 
función llamada
– Que  el valor de la variable se haya modificado en la 
función  llamada

63
Funciones
Paso de parámetros

Paso por valor:
– Al volver no se ha modificado la variable original
– En la llamada se pasa su valor

Por referencia
– Al volver se ha modificado la variable original
– En la llamada se pasa la referencia o dirección de memoria en la 
que se encuentran
– Utilidad: para que una función calcule más de un valor (return 
sólo puede devolver, como mucho, un único valor)

64
Funciones
Sencuencia en la llamada a una función

Almacenamiento del contexto del punto desde el que se llama 
(posición de ejecución, entorno de variables locales) y de los valores 
de los argumentos

Salto al nuevo punto de ejecución

Creación de nuevo ámbito o contexto:
– Parámetros, como variables locales a la función
– Variables locales propias de la función

(Ejecución de sentencias de la función)

65
Funciones
Sencuencia en la vuelta de una función

Almacenamiento del posible valor de retorno

Destrucción del contexto (variables locales) de la función llamada

Vuelta (salto) al punto original de la ejecución

Recuperación del valor devuelto por la función

Recuperación del contexto de la función llamante

66
Funciones
Función especial: main

Declaración con varias posibilidades:
– int main (void)
– int main (int argc, char*argv[])
– Menos estándar: int main (int argc, char*argv[], char **envp)
(envp: array de cadenas siendo el elemento final la cadena NULL)

El valor de retorno se puede recoger desde el programa que 
hace la llamada en tiempo de ejecución.
Ej. en bash, de la forma:
echo $?
o bien:
a=$?
echo $a
67
Funciones
Documentación de una función

Declaración:
– Nombre
– Tipo del valor de retorno
– Nº y tipo de Parámetros

Fichero(s) cabecera

Objetivo y descripción

Valor de retorno

Observaciones

68
Funciones
Librerías

Definición:
– Conjunto de ficheros objeto (compilados), con funciones y/o 
variables listas para ser enlazadas
– Paquetizados según un formato específico

Clasificaciones:
– Estándares o no; http://en.wikipedia.org/wiki/C_standard_library
– Programadas por el usuario o del sistema

69
Funciones
Librerías

Toda librería consta de:
– Fichero .h: con declaraciones de funciones externas,...
(En GNU/Linux están en /usr/include)
– Fichero .o,.a,.la de código compilado
(En GNU/Linux están en /usr/lib, ej. libc.a)
– Ficheros .c de código fuente. Importancia del Software libre

Correspondencia de fichero compilado a fichero cabecera 
no siempre 1 a 1:
libm.a ............ math.h
libc.a ............. stdio.h, stdlib.h, string.h,...

70
Arrays
Concepto de Arrays

Tipo de dato que representa un conjunto de datos de igual 
tipo, almacenados en posiciones contiguas de memoria

Tiene una o varias dimensiones:
– Unidimensionales (semejante avectores)
– Bidimensionales (semejante a matrices de 2 dimensiones)
– ...
– Multidimensionales

71
Arrays
Concepto de Arrays

Distinguir:
– Nº máximo de elementos : no puede ser modificado 
dinámicamente en tiempo de ejecución
– Nº de elementos inicializados

Tamaño en bytes de un array =
nº máximo de elementos x tamaño de cada elemento

72
Arrays
Arrays unidimensionales

Disposición en memoria

Sintaxis para la declaración:
– Modalidad 1: sin inicialización
<tipo> <nombre_var_array> [num_elem];
– Modalidad 2: con inicialización. En este caso el nº de elementos es 
opcional:
<tipo> <nombre_var_array> [num_elem]={valor1, valor2,...};
<tipo> <nombre_var_array> []={valor1, valor2,...};

En caso de indicar el nº de elementos, éste ha de ser una 
constante

73
Arrays
Arrays unidimensionales

Acceso a los elementos de un array:
– Cada elemento se referencia como:
<nombre_var_array> [<indice>]
siendo <indice> un valor entre 0 y <num_elem>­1

Dualidad array­puntero:
– Los elementos de un array se pueden referenciar con notación de 
puntero, de la forma:
var_array + N ≡ &var_array[N]
– El nombre del array representa la dirección de memoria en la que 
se encuentra el primer elemento:
var_array ≡ &var_array[0]

74
Arrays
Arrays unidimensionales como parámetros de funciones

Posibilidades:
– Elementos del array uno a uno. Problema: muchos parámetros
– Array completo

Array completo: por referencia
– Pasando el nombre se pasa la dirección de todo el array.
– Los valores de los elementos del array pueden ser modificados 
dentro de la función
– Para informar a la función del nº de elementos, puede hacerse:

Empleando otro parámetro para la función

Usando constantes con igual valor en la función llamante y la función 
llamada

75
Arrays
Arrays unidimensionales como parámetros de funciones

Sintaxis de la declaración de un array unidimensional como 
parámetro por referencia:
– Con notación array:
<tipo_func><nombre_func (...,<tipo> [],...);
– Con notación puntero:
<tipo_func><nombre_func (...,<tipo> *,...);

76
Arrays
Arrays unidimensionales como resultado de funciones

No se debe devolver un array como resultado de una 
función en el caso de que dicho array se haya declarado 
como variable local a la función, ya que al finalizar ésta la 
zona de memoria del array no es válida (se destruye el 
contexto de la función llamada).

Otras formas:
– Modificar por referencia un array pasado como parámetro desde la 
función que hace la llamada.
– Devolver un puntero a una zona de memoria reservada 
dinámicamente dentro de la función.

77
Arrays
Arrays bidimensionales

Disposición en memoria: primero filas y luego columnas

Sintaxis para la declaración:
– Modalidad 1: sin inicialización
<tipo> <nombre_var_array> [num_filas][num_cols];

– Modalidad 2: con inicialización. En este caso el nº de filas es 
opcional:
<tipo> <nombre_var_array> [num_filas][num_cols]={valor1, valor2,...};

<tipo> <nombre_var_array> [num_filas][num_cols]={array_u1, array_u2,...};

(siendo array_u1,... arrays unidimensionales de num_cols elementos)
<tipo> <nombre_var_array> [][num_cols]={valor1, valor2,...};

<tipo> <nombre_var_array> [][num_cols]={array_u1, array_u2,...};

(siendo array_u1,... arrays unidimensionales de num_cols elementos)
78
Arrays
Arrays bidimensionales

Sintaxis de acceso a los elementos de un array 
bidimensional:
<nombre_var_array> [<indice_fila>][<indice_col>]

Sintaxis de la declaración de un array bidimensional como 
parámetro por referencia: indicar el tamaño de todas las 
dimensiones menos la primera.
<tipo_func><nombre_func (...,<tipo> [][num_cols],...);

79
Arrays
Operadores de comparación y asignación

Operadores de comparación (==,!=) entre arrays:
– Comparan las direcciones de los arrays, pero no el contenido.
– Para comparar los contenidos hay que emplear un bucle.

Operador de asignación (=) entre arrays:
– No es aplicable.
– Para hacer la copia de un array a otro hay que hacerlo elemento a 
elemento o mediante funciones de librería.

80
Arrays
Precauciones

Acceso indebido a memoria: no se debe acceder a zonas de 
memoria no declaradas por el programa,
ej. en arrays, acceso a elementos más allá de <tamaño­1>
– Puede ocasionar errores graves en lectura, y muy graves en 
escritura.
– No es un error detectado en tiempo de compilación

Inicialización de arrays completos, de la forma { }: sólo en 
la declaración. Si no, elemento a elemento.

Los elementos de un array declarado como variable local 
dentro de una función llamada, no son válidas a la vuelta 
en la función llamante.

81
Cadenas de caracteres
Introducción

Definición: es un array de caracteres que termina con el 
carácter '\0' (NULL).

Una constante literal de cadena tiene dos posibles 
representaciones:
– Entre “ “. El compilador reserva automáticamente un byte más 
para el carácter final '\0'. Ej.
“cadena”
– Caracteres entre { } siendo el último '\0'. Ej:
{'c','a','d','e','n','a','\0'}

82
Cadenas de caracteres
Declaración

No son un tipo predefinido en C. Hay dos posibilidades:
– Array de char. En memoria:
char a[]=”kaixo”;
+---+---+---+---+---+---+
a | k | a | i | x | o |\0 |
+---+---+---+---+---+---+

– Puntero a char. En memoria:
char *p=”kaixo”;
+---+ +---+---+---+---+---+---+
p | * =====>| k | a | i | x | o |\0 |
+---+ +---+---+---+---+---+---+

83
Cadenas de caracteres
Declaración

Array de char:
– Se hace una reserva de memoria igual al nº de elementos indicado 
en la longitud del array, o si ésta no se indica igual a la longitud de 
la cadena a la que se inicializa más uno.
– Sólo se puede igualar a una cadena constante en la inicialización. 
Más adelante no se puede igualar a otras cadenas, sean constantes 
o variables

Puntero a char:
– Se hace una reserva de memoria para almacenar el tamaño del 
puntero, y otra para almacenar los caracteres igual que en el caso 
anterior.
– Se puede igualar a otras cadenas en cualquier momento.
– Si al declararlo se inicializa, su contenido no puede ser modificado
84
Cadenas de caracteres
Sintaxis para la declaración como array de char

Sin inicialización:
char str[<longitud>];

Con inicialización. En este caso la longitud es opcional:
char str[<longitud>]=”cadena”;
char str[<longitud>]={'c','a','d','e','n','a','\0'};
char str[]=”cadena”;
char str[]={'c','a','d','e','n','a','\0'};
char str[]={num1,num2,...,,numN,0};
– En caso de indicarse <longitud>, se almacena ese nº de bytes, 
independientemente de que no coincida con la longitud de 
cadena+1

85
Cadenas de caracteres
Sintaxis para la declaración como puntero a char

Sin inicialización:
char *str;

Con inicialización:
char *str=”cadena”;
– No es posible modificar a posteriori el contenido.
– No es válida la sintaxis:
char *str={'c','a','d','e','n','a','\0'};

86
Cadenas de caracteres
Operadores de comparación y asignación

Operadores de comparación (==,!=) entre cadenas de 
caracteres:
– Comparan las direcciones de los punteros, pero no el contenido.
– Para comparar los caracteres de las cadenas se debe emplear la 
función strcmp

Operador de asignación (=) entre cadenas de caracteres:
– Si una cadena se declara como array de char, no se puede igualar a 
otra cadena (excepto en la inicialización a un literal string).
– Si una cadena se declara como char *:

Para copiar los caracteres de una cadena a otra no vale con igualar los 
punteros que las designan. Hay que copiar caracter a caracter (ej. con 
un bucle o con la función strcpy).

Si se iguala a un literal string después no puede variar su contenido. 87
Cadenas de caracteres
Funciones

Declaradas en stdio.h:
– E/S en stdin y stdout: printf, scanf, puts, gets
– E/S en un stream: fprintf, fscanf, fputs, fgets
– E/S en otra cadena: sprintf, sscanf

Declaradas en string.h:
– Longitud (nº de caracteres) de una cadena: strlen
– Copia de una cadena a otra: strcpy
– Concatenación de una cadena detrás de otra: strcat
– Comparación de dos cadenas: strcmp
– Búsqueda de en una cadena: strchr, strrchr, strstr

88
Cadenas de caracteres
Precauciones

Carácter '\0' final:
– A nivel de almacenamiento, considerar un byte adicional para el 
carácter '\0' final
– Diferenciar entre la longitud de la cadena (el nº de caracteres), y el 
nº de bytes ocupados
– Todas las funciones que operan sobre cadenas sólo se detienen (ej. 
strlen, sprintf, strcpy) cuando encuentran '\0'.

89
Cadenas de caracteres
Precauciones

Memoria controlada:
– No se puede modificar el contenido de una cadena de tipo puntero 
a char si apunta a un literal.
– Gestión de memoria: al copiar una cadena a otra (sprintf, strcat, 
strcpy), hay que tener espacio previamente reservado en el 
destino. Posibles problemas:

Array demasiado corto.

Puntero sin reserva de espacio.
– La función gets es insegura porque no comprueba desbordamiento 
de buffers. Mejor usar fgets (ver tema de ficheros y streams).

90
Estructuras
Introducción

Tipo de dato que almacena un conjunto de datos de 
distinto tipo bajo un mismo nombre.

Pasos para el empleo de estructuras:
– Declaración de la estructura fuera de funciones, antes de usarla en 
variables y funciones.
– Declaración de las variables de tipo struct y/o funciones que 
devuelvan tipo struct

91
Estructuras
Declaraciones

Sintaxis para declarar la estructura:
struct <nombre_estructura> {
<declaración [e inicialización] campo 1>;
<declaración [e inicialización] campo 2>;
...
<declaración [e inicialización] campo n>;
};

Ha de hacerse fuera de y antes de la función donde se use 
(main u otras): variables o valor de retorno de ese tipo.

Si se inicializa algún campo, queda inicializado por defecto 
para todas las variables de tipo estructura
92
Estructuras
Declaraciones

Sintaxis para declarar variables y valores de retorno de 
funciones de tipo estructura:
struct <nombre_estructura> <variable>;
struct <nombre_estructura> <funcion> ...

93
Estructuras
Uso de estructuras

Acceso a los campos de estructura:
– Si es una variable de tipo estructura:
operador .
<nombre_variable_estructura>.<nombre_campo>
– Si es una variable de tipo puntero a estructura:
operador ­>
<ptr_a_estructura> -> <nombre_campo>
   Equivale a: (*<ptr_a_estructura>).<nombre_campo>

Paso de parámetros de tipo estructuras a funciones:
mejor pasar por referencia, en vez de por valor

94
Estructuras
Operadores de comparación y asignación

Operadores de comparación (==,!=) entre variables de 
tipo struct: no son válidos, y hay que hacer una 
comparación campo a campo.

Operador de asignación (=) entre estructuras: sí es posible 
copiar una variable de tipo estructura a otra del mismo tipo 
(internamente se produce una copia campo a campo), 
incluso aunque alguno de los campos sea de tipo array.

95
Tipos combinados


Array de punteros
char *nombres[10];

Array de estructuras
struct persona mi_clase[10];

Estructura con tipos de campos variados:
struct alumna {
struct nom_ap1_ap2 identificador;
float notas[10];
char *mem_dinamica;
};

96
Tipos combinados
Puntero a ...

En general útil para funciones con paso de parámetros por 
referencia

Puntero a estructura:
struct persona * ptr_struct;

Puntero a puntero. Como parámetro de una función se 
modificaría el valor de un puntero (no el contenido 
apuntado por el mismo).
int ** ptr_ptr;

Puntero a array: su uso es infrecuente, y se emplea para 
pasar por referencia un array multidimensional con 
notación de puntero:
char (*ptr_a_array)[]; 97
Gestión de memoria dinámica
Introducción

Reserva estática:
– En tiempo de compilación. Ej. arrays
– No puede modificarse el tamaño ni liberarse en tiempo de 
ejecución

Reserva dinámica:
– En tiempo de ejecución.
– Sí puede modificarse el tamaño de la reserva y liberarse en tiempo 
de ejecución

Funciones:
– Declaradas en malloc.h o en stdlib.h (con incluir uno es suficiente)
– Reserva: calloc, malloc, realloc
– Liberación: free 98
Gestión de memoria dinámica
Precauciones

Comprobar errores devueltos

Liberar siempre lo reservado

99
Ficheros y streams
Introducción

Ficheros físicos: información almacenada en un dispositivo: 
disco (HD, CD, DVD), USB, memoria,...
– Características: nombre, tamaño, ubicación, permisos, propietario
– Ubicación o path: en GNU/Linux directorios separados por '/'

Fichero lógico: abstracción de un lenguaje de programación 
para acceder a los ficheros físicos.

100
Ficheros y streams
Introducción

Contenido de los ficheros:
– Caracteres ASCII, con líneas separadas. ('\n' en GNU/Linux)
– Caracteres no ASCII binarios (posiblemente contendrá caracteres 
ASCII). Ejs:

Audio, video, ejecutables

Texto formateado (rtf, openoffice,...)

El contenido es independiente del nombre, ej. fichero1.dat, 
fichero.txt

101
Ficheros y streams
Streams

Son los ficheros lógicos empleados en C: objetos para 
manejar ficheros y dispositivos.

El tipo de un stream es: FILE*

Definición en stdio.h. Otros símbolos:
– NULL: 0
– EOF: ­1 (end of file)

102
Ficheros y streams
Conceptos de streams

Nombres de ficheros físicos

Operaciones típicas:
– Lectura y escritura. Caracteres ascii o binarios. Buffers de streams
– Desplazamiento. Indicador de posición.

Abrir streams. Lo primero para trabajar con streams. Modos 
de apertura:
– r, r+, w, w+, a, a+
– Diferenciación binario/ASCII: está definido en el estándar ANSI C, 
pero en los sistemas POSIX (GNU/Linux incluido) no hay 
distinción

Indicadores de error y de fin de fichero

Cerrar streams. Obligatorio para los streams abiertos. 103
Ficheros y streams
Funciones

Declaradas en stdio.h y stdio_ext.h (éste no es estándar)

Streams:
– E/S: contenido texto(=ASCII) o binario. Ver cuadro sinóptico
– Volcado de buffers de salida y entrada: fflush,__fpurge
– Abrir, cerrar y reasignar stream: fopen, fclose,freopen
– Indicadores  de fin de fichero y error: feof, ferror,
clearerr
– Desplazar y obtener indicador de posición: fseek, rewind,
ftell

Ficheros:
– Borrar, renombrar: remove, rename
104
Ficheros y streams
Streams predefinidos

Hay 3 streams especiales:
Stream Definición Por defecto Valor
stdin Entrada estándar Teclado 0
stdout Salida estándar Pantalla 1
stderr Salida de errores Pantalla 2


Al ejecutar un programa ya están abiertos, y además de los 
dispositivos a los que están asignados por defecto, pueden 
ser redirigidos. Útiles en redirecciones y pipes.
Ej. en bash:
– programa >fichero1 <fichero2
– programa1 | programa 2 > fichero
– programa 2>fichero1
105
Ficheros y streams
Precauciones

Comprobar errores devueltos

Fijarse si la función de lectura o escritura opera sobre un 
fichero de texto o binario

Fijarse si la función opera sobre un nombre de fichero o 
sobre un stream. En este caso, tener en cuenta el orden:
– Abrir el stream antes de leer/escribir
– Cerrar el stream tras su uso, antes o después

En funciones con formato (fprintf, fscanf,...) hacer 
corresponder el nº de parámetros al nº de %

106
Referencias


http://www.lysator.liu.se/c/ 

http://www.faqs.org/faqs/C­faq/faq/

107

También podría gustarte