Está en la página 1de 138

Manual de C

He tor Tejeda Villela

Indi e general
1. Compila ion de un programa en C/C++

1.1. Crea ion, ompila ion y eje u ion de un programa . . . .


1.1.1. Crea ion del programa . . . . . . . . . . . . . . . .
1.1.2. Compila ion . . . . . . . . . . . . . . . . . . . . .
1.1.3. Eje u ion del programa . . . . . . . . . . . . . . .
1.2. El modelo de ompila ion de C . . . . . . . . . . . . . . .
1.3. El prepro esador . . . . . . . . . . . . . . . . . . . . . . .
1.4. Compilador de C . . . . . . . . . . . . . . . . . . . . . . .
1.5. Ensamblador . . . . . . . . . . . . . . . . . . . . . . . . .
1.6. Ligador . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.7. Algunas op iones utiles del ompilador . . . . . . . . . . .
1.8. Uso de las bibliote as . . . . . . . . . . . . . . . . . . . .
1.9. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.1. Crea ion de una bibliote a estati a . . . . . . . . .
1.9.2. Crea ion de una bibliote a ompartida . . . . . . .
1.10. Fun iones de la bibliote a de UNIX . . . . . . . . . . . . .
1.10.1. En ontrando informa ion a er a de las bibliote as.
1.11. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . .

2. Prin ipios de C
2.1.
2.2.
2.3.
2.4.

Orgenes del C . . . . . . . . . . . . .
Cara tersti as de C . . . . . . . . . .
Estru tura de un programa en C . . .
Variables . . . . . . . . . . . . . . . .
2.4.1. De ni ion de variables globales
2.4.2. Le tura y es ritura de variables
2.5. Constantes . . . . . . . . . . . . . . .
2.6. Operadores Aritmeti os . . . . . . . .
2.7. Operadores de Compara ion . . . . . .
2.8. Operadores logi os . . . . . . . . . . .
2.9. Orden de pre eden ia . . . . . . . . .
2.10. Ejer i ios . . . . . . . . . . . . . . . .

3. Estru turas Condi ionales


3.1.
3.2.
3.3.
3.4.

La senten ia if . .
El operador ? . . .
La senten ia swit h
Ejer i ios . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

1
1
1
2
2
2
3
3
3
3
4
5
5
6
7
7
8

10

10
10
11
12
13
14
15
15
16
16
16
18

19

19
20
21
23

INDICE GENERAL

ii

4. Itera ion
4.1.
4.2.
4.3.
4.4.
4.5.

La senten ia for . . . . .
La senten ia while . . .
La senten ia do-while .
Uso de break y ontinue
Ejer i ios . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

5. Arreglos y adenas

24

24
25
26
28
29

32

5.1. Arreglos unidimensionales y multidimensionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32


5.2. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

6. Fun iones
6.1.
6.2.
6.3.
6.4.

Fun iones void . . . . .


Fun iones y arreglos . .
Prototipos de fun iones
Ejer i ios . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

7. Mas tipos de datos

7.1. Estru turas . . . . . . . . . . . . . . . . .


7.1.1. De ni ion de nuevos tipos de datos
7.2. Uniones . . . . . . . . . . . . . . . . . . .
7.3. Conversion de tipos ( asts) . . . . . . . .
7.4. Enumera iones . . . . . . . . . . . . . . .
7.5. Variables estati as . . . . . . . . . . . . .
7.6. Ejer i ios . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

8. Apuntadores
8.1.
8.2.
8.3.
8.4.
8.5.
8.6.
8.7.
8.8.
8.9.

De ni ion de un apuntador . . . . . . . . . . . .
Apuntadores y Fun iones . . . . . . . . . . . . .
Apuntadores y arreglos . . . . . . . . . . . . . . .
Arreglos de apuntadores . . . . . . . . . . . . . .
Arreglos multidimensionales y apuntadores . . .
Ini ializa ion estati a de arreglos de apuntadores
Apuntadores y estru turas . . . . . . . . . . . . .
Fallas omunes on apuntadores . . . . . . . . . .
Ejer i ios . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

9. Asigna ion dinami a de memoria y Estru turas dinami as


9.1.
9.2.
9.3.
9.4.
9.5.

Uso de mallo , sizeof y


allo y reallo . . . .
Listas ligadas . . . . . . .
Programa de revision . . .
Ejer i ios . . . . . . . . .

free

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.

10.Topi os avanzados on apuntadores

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

36

37
37
38
39

40

40
41
42
43
44
44
45

46

46
49
49
51
51
53
53
54
55

56
56
57
58
58
61

63

10.1. Apuntadores a apuntadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63


10.2. Entrada en la lnea de omandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
10.3. Apuntadores a fun iones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

INDICE GENERAL

iii

10.4. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

11.Operadores de bajo nivel y ampos de bit


11.1. Operadores sobre bits
11.2. Campos de bit . . . .
11.2.1. Portabilidad . .
11.3. Ejer i ios . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

12.El prepro esador de C

12.1. Dire tivas del prepro esador . . . . . . . .


12.1.1. #define . . . . . . . . . . . . . .
12.1.2. #undef . . . . . . . . . . . . . . .
12.1.3. #in lude . . . . . . . . . . . . . .
12.1.4. #if In lusion ondi ional . . . . .
12.2. Control del prepro esador del ompilador
12.3. Otras dire tivas del prepro esador . . . .
12.4. Ejer i ios . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

69

69
70
71
72

73

73
73
74
74
75
76
76
77

13.C, UNIX y las bibliote as estandar

78

14.Bibliote a <stdlib.h>

80

13.1. Ventajas del usar UNIX on C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78


13.2. Uso de fun iones de bibliote as y llamadas del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
14.1. Fun iones aritmeti as . .
14.2. Numeros aleatorios . . . .
14.3. Conversion de adenas . .
14.4. Busqueda y ordenamiento
14.5. Ejer i ios . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

15.Bibliote a <math.h>

80
81
82
83
85

86

15.1. Fun iones matemati as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86


15.2. Constantes matemati as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

16.Entrada y salida (E/S) stdio.h

16.1. Reportando errores . . . . . . . . . . . . . . . . . .


16.1.1. perror() . . . . . . . . . . . . . . . . . . .
16.1.2. errno . . . . . . . . . . . . . . . . . . . . .
16.1.3. exit . . . . . . . . . . . . . . . . . . . . . .
16.2. Flujos . . . . . . . . . . . . . . . . . . . . . . . . .
16.2.1. Flujos prede nidos . . . . . . . . . . . . . .
16.3. E/S Basi a . . . . . . . . . . . . . . . . . . . . . .
16.4. E/S formateada . . . . . . . . . . . . . . . . . . . .
16.4.1. printf . . . . . . . . . . . . . . . . . . . .
16.4.2. s anf . . . . . . . . . . . . . . . . . . . . .
16.5. Ar hivos . . . . . . . . . . . . . . . . . . . . . . . .
16.5.1. Le tura y es ritura de ar hivos . . . . . . .
16.6. sprintf y ss anf . . . . . . . . . . . . . . . . . .
16.6.1. Peti ion del estado del ujo . . . . . . . . .
16.7. E/S de bajo nivel o sin alma enamiento intermedio

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

88

88
88
88
89
89
90
90
90
91
92
92
93
93
94
94

INDICE GENERAL

iv

16.8. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

17.Manejo de adenas <string.h>

17.1. Fun iones basi as para el manejo de adenas


17.1.1. Busqueda en adenas . . . . . . . . . .
17.2. Prueba y onversion de ara teres < type.h>
17.3. Opera iones on la memoria <memory.h> . .
17.4. Ejer i ios . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

18.A eso de Ar hivos y llamadas al sistema de dire torios

18.1. Fun iones para el manejo de dire torios <unistd.h> . . . . . . . . . . . .


18.1.1. Busqueda y ordenamiento de dire torios: sys/types.h,sys/dir.h
18.2. Rutinas de manipula ion de ar hivos: unistd.h, sys/types.h, sys/stat.h . .
18.2.1. Permisos de a esos a ar hivos . . . . . . . . . . . . . . . . . . . .
18.2.2. Estado de un ar hivo . . . . . . . . . . . . . . . . . . . . . . . . . .
18.2.3. Manipula ion de ar hivos: stdio.h, unistd.h . . . . . . . . . . . . .
18.2.4. Crea ion de ar hivos temporales: <stdio.h> . . . . . . . . . . . .
18.3. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

19.Fun iones para el tiempo

19.1. Fun iones basi as para el tiempo . . . . . . . . . . . . . . . . . . .


19.2. Ejemplos de apli a iones de fun iones del tiempo. . . . . . . . . . .
19.2.1. Ejemplo 1: Tiempo (en segundos) para ha er algun al ulo.
19.2.2. Ejemplo 2: Ini ializar la semilla de un numero aleatorio. . .
19.3. Ejer i ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20.Control de pro esos: <stdlib.h>, <unistd.h>


20.1. Eje utando omandos de UNIX desde C
20.2. exe l() . . . . . . . . . . . . . . . . .
20.3. fork() . . . . . . . . . . . . . . . . . .
20.4. wait() . . . . . . . . . . . . . . . . . .
20.5. exit() . . . . . . . . . . . . . . . . . .
20.6. Ejer i ios . . . . . . . . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

21.Compila ion de Programas on Ar hivos Multiples


21.1. Ar hivos Cabezera . . . . . . . . . . . . . . .
21.2. Variables y Fun iones Externas . . . . . . . .
21.2.1. Al an e de las variables externas . . .
21.3. Ventajas de Usar Varios Ar hivos . . . . . . .
21.4. Como dividir un programa en varios ar hivos
21.5. Organiza ion de los Datos en ada Ar hivo .
21.6. La utilera Make . . . . . . . . . . . . . . . .
21.6.1. Programando Make . . . . . . . . . .
21.7. Crea ion de un Ar hivo Make (Make le) . . .
21.8. Uso de ma ros on Make . . . . . . . . . . . .
21.9. Eje u ion de Make . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

98

. 98
. 99
. 101
. 101
. 102

103

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

. 103
. 104
. 106
. 106
. 106
. 108
. 108
. 108

109

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

. 109
. 110
. 110
. 110
. 111

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

. 112
. 112
. 113
. 114
. 114
. 117

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

112

118

. 118
. 120
. 120
. 121
. 121
. 122
. 123
. 123
. 124
. 125
. 126

INDICE GENERAL

22.Comuni a ion entre pro esos (IPC Interpro ess Communi ation), PIPES

127

22.1. Entubando en un programa de C <stdio.h> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127


22.1.1. popen() Tubera formateada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
22.1.2. pipe() Tubera de bajo nivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

Cap
tulo 1

Compila i
on de un programa en C/C++
En esta aptulo se dan las pro esos basi os que se requieren para ompilar un programa de C. Se des ribe tambien
el modelo de ompila ion de C y tambien omo C soporta bibliote as adi ionales.

1.1. Crea ion, ompila ion y eje u ion de un programa


1.1.1. Crea ion del programa
Se puede rear un ar hivo que ontenga el programa ompleto, omo en los ejemplos que se tienen mas adelante.
Se puede usar ualquier editor de textos ordinario on el que se este familiarizado. Un editor disponible en la mayora
de los sistemas UNIX es vi, y en Linux se puede usar pi o.
Por onven ion el nombre del ar hivo debe terminar on \. " por ejemplo: miprograma. progprueba. . El ontenido del ar hivo debera obede er la sintaxis de C.

1.1.2. Compila ion


Existen mu hos ompiladores de C. El es el ompilador estandar de Sun. El ompilador GNU de C es g , el
ual es bastante popular y esta disponible en varias plataformas.
Existen tambien ompiladores equivalentes de C++ los uales usualmente son nombrados omo CC. Por ejemplo,
Sun provee CC y GNU GCC. El ompilador de GNU es tambien denotado omo g++.
Existen otros ompiladores menos omunes de C y C++. En general todos los ompiladores men ionados operan
esen ialmente de la misma forma y omparten mu has op iones omunes en la lnea de op iones. Mas adelante se
listan y se dan ejemplos de op iones omunes de los ompiladores. Sin embargo, la mejor referen ia de ada ompilador
es a traves de las paginas en lnea, del manual del sistema. Por ejemplo: man g .
Para ompilar el programa usaremos el omando g . El omando debera ser seguido por el nombre del programa
en C que se quiere ompilar. Un determinado numero de op iones del ompilador pueden ser indi adas tambien. Por
el momento no haremos uso de estas op iones todava, se iran omentando algunas mas esen iales.
Por lo tanto, el omando basi o de ompila ion es:
g programa.

donde programa. es el nombre del ar hivo.


Si hay errores obvios en el programa (tales omo palabras mal es ritas, ara teres no te leados u omisiones de
punto y oma), el ompilador se detendra y los reportara.
Podra haber desde luego errores logi os que el ompilador no podra dete tar. En el aso que esta fuera la situa ion
se le estara indi ando a la omputadora que haga las opera iones in orre tas.
1

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

Cuando el ompilador ha terminado on exito, la version ompilada, o el eje utable, es dejado en un ar hivo
llamado a.out, o si la op ion -o es usada on el ompilador, el nombre despues de -o es el nombre del programa
ompilado.
Se re omienda y es mas onveniente usar la op ion -o on el nombre del ar hivo eje utable omo se muestra a
ontinua ion:
g -o programa programa.

el ual pone el programa ompilado en el ar hivo del programa se~nalado, en este aso en programa, en vez del ar hivo
a.out.

1.1.3. Eje u ion del programa


El siguiente estado es orrer el programa eje utable. Para orrer un eje utable en UNIX, simplemente se es ribe
el nombre del ar hivo que lo ontiene, en este aso programa (o a.out ).
Con lo anterior, se eje uta el programa, mostrando algun resultado en la pantalla. En este estado, podra haber
errores en tiempo de eje u ion (run-time errors ), tales omo division por ero, o bien, podran ha erse evidentes al
ver que el programa no produ e la salida orre ta.
Si lo anterior su ede, enton es se debe regresar a editar el ar hivo del programa, re ompilarlo, y eje utarlo
nuevamente.

1.2. El modelo de ompila ion de C


En la gura 1.1 se muestran las distintas etapas que ubre el ompilador para obtener el odigo eje utable.
CODIGO FUENTE
PREPROCESADOR

COMPILADOR
CODIGO EN
ENSAMBLADOR
ENSAMBLADOR
LIBRERIAS

CODIGO OBJETO
LIGADOR

CODIGO EJECUTABLE

Figura 1.1: Modelo de ompila ion de C.

1.3. El prepro esador


Esta parte del pro eso de ompila ion sera ubierta on mas detalle en el aptulo 12 referente al prepro esador.
Sin embargo, se da alguna informa ion basi a para algunos programas de C.
El prepro esador a epta el odigo fuente omo entrada y es responsable de:

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

quitar los omentarios


interpretar las dire tivas del prepro esador las uales ini ian on #.
Por ejemplo:
#in lude | in luye el ontenido del ar hivo nombrado. Estos son usualmente llamados ar hivos de abe era
(header). Por ejemplo:




#in lude <math.h> | Ar hivo de la bibliote a estandar de matemati as.


#in lude <stdio.h> | Ar hivo de la bibliote a estandar de Entrada/Salida.

#define | de ne un nombre simboli o o onstante. Sustitu ion de ma ros.

#define TAM_MAX_ARREGLO 100

1.4. Compilador de C
El ompilador de C tradu e el odigo fuente en odigo de ensamblador. El odigo fuente es re ibido del prepro esador.

1.5. Ensamblador
El ensamblador rea el odigo fuentei o los ar hivos objeto. En los sistemas on UNIX se podran ver los ar hivos
on el su jo .o.

1.6. Ligador
Si algun ar hivo fuente ha e referen ia a fun iones de una bibliote a o de fun iones que estan de nidas en otros
ar hivos fuentes, el ligador ombina estas fun iones ( on main()) para rear un ar hivo eje utable. Las referen ias a
variables externas en esta etapa son resueltas.

1.7. Algunas op iones utiles del ompilador


Des rito el modelo basi o de ompila ion, se daran algunas op iones utiles y algunas ve es esen iales. De nueva
uenta, se re omienda revisar las paginas de man para mayor informa ion y op iones adi ionales.
-E

Se ompilador se detiene en la etapa de prepro esamiento y el resultado se muestra en la salida


estandar.
g -E ar h1.
-

Suprime el pro eso de ligado y produ e un ar hivo .o para ada ar hivo fuente listado. Despues los
ar hivos objeto pueden ser ligados por el omando g , por ejemplo:
g ar h1.o ar h2.o ... -o eje utable
-lbibliote a

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

Liga on las bibliote as objeto. Esta op ion debera seguir los argumentos de los ar hivos fuente. Las
bibliote as objeto son guardadas y pueden estar estandarizadas, un ter ero o usuario las rea. Probablemente la bibliote a mas omunmente usada es la bibliote a matemati a (math.h). Esta bibliote a
debera ligarse expl itamente si se desea usar las fun iones matemati as (y por supuesto no olvidar el
ar hivo abe era #in lude <math.h>, en el programa que llama a las fun iones), por ejemplo:
g al . -o al -lm

Mu has otras bibliote as son ligadas de esta forma.


-Ldire torio

Agrega dire torios a la lista de dire torios que ontienen las rutinas de la bibliote a de objetos. El
ligador siempre bus a las bibliote as estandares y del sistema en /lib y /usr/lib. Si se quieren ligar
bibliote as personales o instaladas por usted, se tendra que espe i ar donde estan guardados los ar hivos,
por ejemplo:
g prog. -L/home/minombr/mislibs milib.a
-Itraye toria

Agrega una traye toria o ruta a la lista de dire torios en los uales se bus aran los ar hivos abe era
#in lude on nombres relativos (es de ir, los que no empiezan on diagonal /).
El pro esador por default, primero bus a los ar hivos #in lude en el dire torio que ontiene el ar hivo
fuente, y despues en los dire torios nombrados on la op ion -I si hubiera, y nalmente, en /usr/in lude.
Por lo tanto, si se quiere in luir ar hivos de abe era guardados en /home/minombr/mis abe eras se
tendra que ha er:
g prog. -I/home/minombr/mis abe eras

Nota: Las abe eras de las bibliote as del sistema son guardados en un lugar espe ial (/usr/in lude) y
no son afe tadas por la op ion -I. Los ar hivos abe era del sistema y del usuario son in ludos en una
manera un po o diferente.

-g

Op ion para llamar las op iones de depura ion (debug). Instruye al ompilador para produ ir informa ion adi ional en la tabla de smbolos que es usado por una variedad de utileras de depura ion. Por
ejemplo, si se emplea el depurador de GNU, el programa debera ompilarse de la siguiente forma para
generar extensiones de GDB:
g -ggdb -o prog prog.
-D

De ne smbolos omo identi adores (-Didenti ador) o omo valores (-Dsmbolo=valor) en una forma
similar a la dire tiva del prepro esador #define).
-v

Muestra en la salida estandar de errores los omandos eje utados en las etapas de ompila ion.

1.8. Uso de las bibliote as


C es un lenguaje extremadamente peque~no. Mu has de las fun iones que tienen otros lenguajes no estan en C,
por ejemplo, no hay fun iones para E/S, manejo de adenas o fun iones matemati as.
La fun ionalidad de C se obtiene a traves de un ri o onjunto de bibliote as de fun iones.

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

Como resultado, mu has implementa iones de C in luyen bibliote as est


andar de fun iones para varias nalidades. Para mu hos propositos basi os estas podran ser onsideradas omo parte de C. Pero pueden variar de
maquina a maquina.
Un programador puede tambien desarrollar sus propias fun iones de bibliote a e in luso bibliote as espe iales de
ter eros, por ejemplo, NAG o PHIGS.
Todas las bibliote as (ex epto E/S estandar) requieren ser expl itamente ligadas on la op ion -l y, posiblemente
on L, omo se se~nalo previamente.

1.9. Ejemplos
1.9.1. Crea ion de una bibliote a estati a
Si se tiene un onjunto de rutinas que se usen en forma fre uente, se podra desear agruparlas en un onjunto de
ar hivos fuente, ompilar ada ar hivo fuente en un ar hivo objeto, y enton es rear una bibliote a on los ar hivos
objeto. Con lo anterior se puede ahorrar tiempo al ompilar en aquellos programas donde sean usadas.
Supongamos que se tiene un onjunto de ar hivos que ontengan rutinas que son usadas fre uentemente, por
ejemplo un ar hivo ubo. :
float ubo(float x)
{
return (x*x*x);
}

y otro ar hivo fa torial.


int fa torial(int n)
{
int i, res=1;
for(i=1; i<=n; i++)
res*=i;
return (res);
}

Para los ar hivos de nuestras fun iones tambien se debe tener un ar hivo de abezera, para que puedan ser usadas,
suponiendo que se tiene el siguiente ar hivo libmm.h on el siguiente ontenido:
extern float ubo(float);
extern int fa torial(int);

El odigo que use la bibliote a que se esta reando podra ser:


/* Programa prueba. */
#in lude "libmm.h"
#define VALOR 4
main()

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

{
printf("El ubo de %d es %f\n",VALOR, ubo(VALOR) );
printf("\t y su fa torial es %d\n",fa torial(VALOR) );
}

Para rear la bibliote a se deben ompilar los ar hivos fuente, que lo podemos ha er de la siguiente forma:
$ g - ubo. fa torial.

Lo ual nos dejara los ar hivos ubo.o y fa torial.o. Despues se debe rear la bibliote a on los ar hivos fuentes,
suponiendo que nuestra bibliote a se llame libmm.a, tendras que ha erlo on el omando ar as:
$ ar r libmm.a ubo.o fa torial.o

Cuando se a tualiza una bibliote a, se ne esita borrar el ar hivo anterior (libmm.a). El ultimo paso es rear un
ndi e para la bibliote a, lo que permite que el ligador pueda en ontrar las rutinas. Lo anterior, lo ha emos on el
omando ranlib, por lo que te learemos ahora:
$ ranlib libmm.a

Los ultimos dos pasos pudieron ser ombinados en uno solo, enton es hubieramos podido te lear:
$ar rs libmm.a ubo.o fa torial.o

Ahora que ya tenemos la bibliote a, es onveniente que oloquemos nuestra bibliote a y el ar hivo abezera en
algun lugar apropiado. Supongamos que dejamos la bibliote a en ~/lib y el hero abezera en ~/in lude, debemos
ha er lo siguiente:
$ mkdir ../in lude
$ mkdir ../lib
$ mv libmm.h ../in lude
$ mv libmm.a ../lib

Si llegaras a modi ar la bibliote a, tendras que repetir la ultima instru ion.


Se debe ahora ompilar el ar hivo on la bibliote a, de la siguiente forma:
g -I../in lude -L../lib -o prueba prueba. -lmm

1.9.2. Crea ion de una bibliote a ompartida


Las ventajas que presentan las bibliote as ompartidas, es la redu ion en el onsumo de memoria, si son usadas
por mas de un pro eso, ademas de la redu ion del tama~no del odigo eje utable. Tambien se ha e el desarrollo mas
fa il, ya que uando se ha e algun ambio en la bibliote a, no se ne esita re ompilar y reenlazar la apli a ion ada
vez. Se requiere lo anterior solo si se modi o el numero de argumentos on los que se llama una fun ion o se ambio
el tama~no de alguna estru tura.
El odigo de la bibliote a ompartida ne esita ser independiente de la posi ion, para ha er posible que sea usado
el odigo por varios programas. Para rear la bibliote a ha erlo de la siguiente forma:
$ g - -fPIC ubo. fa torial.

Para generar la bibliote a dinami a ha er lo siguiente:


$ g -shared -o libmm.so ubo.o fa torial.o

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

No existe un paso para la indexa ion omo o urre en las bibliote as estati as.
Despues habra que mover la bibliote a dinami a a su dire torio orrespondiente (../lib) y pro eder a ompilar
para que nuestro odigo use la bibliote a.
$ g -I../in lude -L../lib -o prueba prueba. -lmm

Nos preguntamos que su ede si hay una bibliote a ompartida (libmm.so) y una estati a (libmm.a) disponibles.
En este aso, el ligador siempre toma la ompartida. Si se desea ha er uso de la estati a, se tendra que nombrar
expl itamente en la lnea de omandos:
$ g -I../in lude -L../lib -o prueba prueba. libmm.a

Cuando se usan bibliote as ompartidas un omando util es ldd, el ual nos informa que bibliote as ompartidas
un programa eje utable usa, a ontinua ion un ejemplo:
$ ldd prueba
libstuff.so => libstuff.so (0x40018000)
lib .so.6 => /lib/i686/lib .so.6 (0x4002f000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Como se ve en ada lnea apare e el nombre de la bibliote a, el amino ompleto a la bibliote a que es usada, y
donde en el espa io de dire iones virtuales la bibliote a esta mapeada.
Si ldd muestra omo salida not found para alguna bibliote a, se van a tener problemas y el programa no podra
ser eje utado. Una forma de arreglarlo es bus ar la bibliote a y olo arla en el lugar orre to para que el programa
loader la en uentre, que siempre bus a por default en lib y /usr/lib. Si se tienen bibliote as en otro dire torio,
rear una variable de ambiente LD_LIBRARY_PATH y poner los dire torios separados por ;.

1.10. Fun iones de la bibliote a de UNIX


El sistema UNIX da un gran numero de fun iones de C. Algunas implementan opera iones de uso fre uente,
mientras otras estan muy espe ializadas en rela ion a su apli a ion.
No reinvente la rueda. Se re omienda revisar si una fun ion en alguna bibliote a existe, en vez de ha er la tarea
de es ribir su propia version. Con lo anterior se redu e el tiempo de desarrollo de un programa. Ya que las fun iones
de la bibliote a han sido probadas, por lo que estaran orregidas, a diferen ia de ualquiera que un programador
pueda es ribir. Lo anterior redu ira el tiempo de depura ion del programa.

1.10.1. En ontrando informa ion a er a de las bibliote as.


El manual de UNIX tiene una entrada para todas las fun iones disponibles. La do umenta ion de fun iones esta
guardada en la se i
on 3 del manual, y hay mu has otras utiles que ha en llamadas al sistema en la se ion 2. Si
ya sabe el nombre de la fun ion que se quiere revisar, puede leer la pagina te leando:
man 3 sqrt

Si no sabe el nombre de la fun ion, una lista ompleta esta in luida en la pagina introdu toria de la se ion 3 del
manual. Para leerlo, te lee:
man 3 intro

Hay aproximadamente 700 fun iones. El numero tiende a in rementarse on ada a tualiza ion al sistema.
En ualquier pagina del manual, la se ion de SYNOPSIS in luye informa ion del uso de la fun ion. Por ejemplo:

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

#in lude <time.h>


har * time( onst time_t *timep);

Lo que signi a que se debe tener


#in lude <time.h>

en el ar hivo del programa que ha e el llamado a time. Y que la fun ion time toma un apuntador del tipo
time_t omo un argumento, y regresa una adena har *.
En la se ion DESCRIPTION se da una peque~na des rip ion de lo que ha e la fun ion.

1.11. Ejer i ios


1. Es ribe, ompila y orre el siguiente programa. Modi a el programa para que in luyas tu nombre y la forma
omo hi istes lo anterior. Para ini iar un omentario usa /* y para terminarlo */:
main()
{
int i;
printf("\t Numero \t\t Cubo\n\n");
for( i=0; i<=20; ++i)
printf("\t %d \t\t\t %d \n",i,i*i*i );
}

2. El siguiente programa usa la bibliote a matemati a. Te lealo, ompilalo y eje utalo. In luye on omentarios
dentro del programa tu nombre y la forma omo hi istes lo anterior.
#in lude <math.h>
main()
{
int i;
printf("\tAngulo \t\t Seno\n\n");
for( i=0; i<=360; i+=15)
printf("\t %d \t\t\t %f \n",i,sin((double) i*M_PI/180.0));
}

3. Bus a en los dire torios /lib y /usr/lib las bibliote as que estan disponibles. Manda 3 nombres de estati as
y 3 de ompartidas.
Use el omando man para obtener detalles de las fun iones de la bibliote a.
Sele iona alguna bibliote a y ve los odigos objetos que ontiene, puedes te lear: ar tv bibliote a
4. Ve en /usr/in lude que ar hivos de abe era estan disponibles.

 DE UN PROGRAMA EN C/C++
CAPITULO 1. COMPILACION

Usa los omandos more o at para ver los ar hivos de texto.


Explora los ar hivos abe era para ver el ontenido, observando las dire tivas de prepro esamiento in lude,
de ne, las de ni iones de los tipos y los prototipos de las fun iones. Envia 10 asos donde se hayan usado
las dire tivas anteriores, indi ando de que ar hivo de abezera las obtuvistes.
5. Supongamos que se tiene un programa en C el ual tiene la fun ion prin ipal en main. y que se tienen otras
fun iones en los ar hivos input. y output. :
>De que forma habra que ompilar y ligar este programa?
>Como se deberan modi ar los omandos anteriores para ligar una bibliote a llamada pro eso1 guardada
en el dire torio estandar de las bibliote as del sistema?
>Como modi aras los omandos anteriores para ligar una bibliote a llamada pro eso2 guardada en tu
dire torio asa?
Algunos ar hivos abe era ne esitan ser ledos y en ontrados en el subdire torio header de su dire torio
asa y tambien en dire torio de trabajo a tual. >Como se modi aran los omandos de ompila ion para
ha er lo se~nalado?

Cap
tulo 2

Prin ipios de C
En este aptulo se ofre e una breve historia del desarrollo del lenguaje C y se onsideran tambien sus ara tersti as.
En el resto del aptulo se ven los aspe tos basi os de los programas de C, tales omo su estru tura, la de lara ion
de variables, tipos de datos y operadores.

2.1. Orgenes del C


El pro eso de desarrollo del lenguaje C se origina on la rea ion de un lenguaje llamado BCPL, que fue desarrollado por Martin Ri hards. El BCPL tuvo in uen ia en un lenguaje llamado B, el ual se uso en 1970 y fue inventado
por Ken Thompson y que permitio el desarrollo de C en 1971, el ual lo invento e implemento Dennis Rit hie. Para
1973 el sistema operativo UNIX estaba asi totalmente es rito en C.
Durante mu hos a~nos el estandar para C fue la version 5 del sistema operativo UNIX, do umentada en \The C
Programming Language" es rito por Brian W. Kernighan and Dennis M. Rit hie in 1978 omunmente referido omo
K&R.
Posteriormente se hi ieron varias implementa iones las uales mostraban las siguientes tenden ias:
Nuevas ara tersti as
Diferen ias de maquinas
Diferen ias de produ tos
Errores en los ompiladores
Malas implementa iones
Esto origino que en el verano de 1983 se estable iera un omite para resolver estas dis repan ias, el ual empezo a
trabajar en un estandar ANSI C, la ual fue ompletada en 1988.

2.2. Cara tersti as de C


Algunas de las ara tersti as mas importantes que de nen el lenguaje y que han permitido que sea tan popular,
omo lenguaje de programa ion son:
Tama~no peque~no.
Uso extensivo de llamadas a fun iones.
10

CAPITULO 2. PRINCIPIOS DE C

11

Comandos breves (po o te leo).


Lenguaje estru turado.
Programa ion de bajo nivel (nivel bit)
Implementa ion de apuntadores { uso extensivo de apuntadores para la memoria, arreglos, estru turas y fun iones
Las diversas razones por la ual se ha onvertido en un lenguaje de uso profesional son:
El uso de onstru tores de alto nivel.
El poder manejar a tividades de bajo-nivel.
El generar programas e ientes.
La posibilidad de poder ser ompilado en una variedad de omputadoras, on po os ambios (portabilidad).
Un punto en ontra es que tiene una dete ion pobre de errores, lo ual en o asiones es problemati o para los
prin ipiantes.

2.3. Estru tura de un programa en C


Un programa de C tiene basi amente la siguiente forma:
Comandos del prepro esador.
De ni iones de tipos.
Prototipos de fun iones { de lara el tipo de fun ion y las variables pasadas a la misma.
Variables
Fun iones
Para un programa se debe tener una fun ion main().
Una fun ion tiene la forma:
tipo nombre_de_la_fun ion (parametros)
{
variables lo ales
senten ias de C
}

Si la de ni ion del tipo es omitida, C asume que la fun ion regresa un tipo entero. Nota: Lo anterior puede ser
una fuente de problemas en un programa.
A ontinua ion se muestra un primer programa:

CAPITULO 2. PRINCIPIOS DE C

Tipo

har
unsigned har
short int
unsigned short int
(long) int
oat
double

12
Tama~no (bytes)

1
1
2
2
4
4
8

Lmite inferior

Lmite superior

|
0
32768
0
231
3;2  1038
1;7  10308

|
255
+32767
65536
+231 1
+3;2  1038
+1;7  10308

Cuadro 2.1: Tipos de C

/* Programa ejemplo */
main()
{
printf( "Me gusta C\n" );
exit (0);
}

NOTAS:
C requiere un punto y oma al nal de ada senten ia.
printf es una fun ion estandar de C, la ual es llamada en la fun ion main().
\n signi a salto de lnea. Salida formateada.
exit() es tambien una fun ion estandar que ha e que el programa termine. En el sentido estri to no es ne esario
ya que es la ultima lnea de main() y de ualquier forma terminara el programa.

En aso de que se hubiera llamado a la fun ion printf de la siguiente forma:


printf(".\n.1\n..2\n...3\n");

La salida tendra la siguiente forma:


.1
..2
...3

2.4. Variables
C tiene los siguientes tipos de datos simples:
Los tipos de datos basi os tiene varios modi adores que les pre eden. Se usa un modi ador para alterar el
signi ado de un tipo base para que en aje on las diversas ne esidades o situa iones. Los modi adores son: signed,
unsigned, long y short.

CAPITULO 2. PRINCIPIOS DE C

13

En los sistemas UNIX todos los tipos int son long int, a menos que se espe i que expl itamente short int.

Nota: no hay un tipo booleano en C | se debera usar har, int o aun mejor unsigned har.

signed, unsigned, long y short pueden ser usados on los tipos har e int. Aunque es permitido el uso de
signed en enteros, es redundante porque la de lara ion de entero por defe to asume un n
umero on signo.

Para de larar una variable en C, se debe seguir el siguiente formato:


tipo lista_variables;

tipo es un tipo valido de C y lista variables puede onsistir en uno o mas indenti adores separados por una
oma. Un identi ador debe omenzar on una letra o un guion bajo.
Ejemplo:
int i, j, k;
float x,y,z;
har h;

2.4.1. De ni ion de variables globales


Una varible global se de lara fuera de todas las fun iones, in luyendo a la fun ion main(). Una variable global
puede ser utilizada en ualquier parte del programa.
Por ejemplo:
short numero, suma;
int numerogr, sumagr;
har letra;
main()
{
...
}

Es tambien posible preini ializar variables globales usando el operador de asigna ion =, por ejemplo:
float suma= 0.0;
int sumagr= 0;
har letra= 'A';
main()
{
...
}

Que es lo mismo que:


float suma;
int sumagr;
har letra;

CAPITULO 2. PRINCIPIOS DE C

14

main()
{
suma = 0.0;
sumagr= 0;
letra = 'A';
...
}

Dentro de C tambien se permite la asigna ion multiple usando el operador =, por ejemplo:
a = b = = d = 3;

. . . que es lo mismo, pero mas e iente que:


a
b

d

=
=
=
=

3;
3;
3;
3;

La asigna ion multiple se puede llevar a abo, si todos los tipos de las variables son iguales.
Se pueden rede nir los tipos de C usando typedef. Como un ejemplo de un simple uso se onsidera omo se rean
dos nuevos tipos real y letra. Estos nuevos tipos pueden ser usados de igual forma omo los tipos prede nidos de C.
typedef float real;
typedef har letra;
/* De lara ion de variables usando el nuevo tipo */
real suma=0.0;
letra sig_letra;

2.4.2. Le tura y es ritura de variables


El lenguaje C usa salida formateada. La fun ion printf tiene un ara ter espe ial para formatear ( %) | un
ara ter enseguida de ne un ierto tipo de formato para una variable.
% ara teres
%s adena de ara teres
%d enteros
%f flotantes

Por ejemplo:
printf("% %d %f", h,i,x);

La senten ia de formato se en ierra entre " ", y enseguida las variables. Asegurarse que el orden de formateo y
los tipos de datos de las variables oin idan.
s anf() es la fun ion para entrar valores a variables. Su formato es similar a printf. Por ejemplo:

CAPITULO 2. PRINCIPIOS DE C

15

s anf("% %d %f %s",& h, &i, &x, ad);

Observar que se antepone & a los nombres de las varibles, ex epto a la adena de ara teres. En el aptulo 8 que
trata sobre apuntadores se revisara mas a fondo el uso de este operador.

2.5. Constantes
ANSI C permite de larar onstantes. Cuando se de lara una onstante es un po o pare ido a de larar una variable,
ex epto que el valor no puede ser ambiado.
La palabra lave onst se usa para de larar una onstante, omo se muestra a ontinua ion:
onst a = 1;
int a = 2;

Notas:
Se puede usar onst antes o despues del tipo.
Es usual ini ializar una onstante on un valor, ya que no puede ser ambiada de alguna otra forma.
La dire tiva del prepro esador #define es un metodo mas exible para de nir onstantes en un programa.
Fre uentemente se ve la de lara ion onst en los parametros de la fun ion. Lo anterior simplemente indi a que
la fun ion no ambiara el valor del parametro. Por ejemplo, la siguiente fun ion usa este on epto:
har *str py( har *dest, onst har *orig);

El segundo argumento orig es una adena de C que no sera alterada, uando se use la fun ion de la bibliote a
para opiar adenas.

2.6. Operadores Aritmeti os


Lo mismo que en otros lenguajes de programa ion, en C se tienen los operadores aritmeti os mas usuales (+ suma,
- resta, * multipli a ion, / division y % modulo).
El operador de asigna ion es =, por ejemplo: i=4; h='y';
In remento ++ y de remento -- unario. Los uales son mas e ientes que las respe tivas asigna iones. Por ejemplo:
x++ es mas rapido que x=x+1.
Los operadores ++ y -- pueden ser pre jos o post jos. Cuando son pre jos, el valor es al ulado antes de que la
expresion sea evaluada, y uando es post jo el valor es al ulado despues que la expresion es evaluada.
En el siguiente ejemplo, ++z es pre jo y -- es post jo:
int x,y,z;
main()
{
x=( ( ++z ) - ( y-- ) ) % 100;
}

Que es equivalente a:

CAPITULO 2. PRINCIPIOS DE C

16

int x,y,z;
main()
{
z++;
x = ( z-y ) % 100;
y--;
}

El operador % (modulo o residuo) solamente trabaja on enteros, aunque existe una fun ion para otantes (15.1
fmod() ) de la bibliote a matemati a.
El operador division / es para division entera y otantes. Por lo tanto hay que tener uidado. El resultado de
x = 3 / 2; es uno, aun si x es de larado omo oat. La regla es: si ambos argumentos en una division son enteros,
ento es el resultado es entero. Si se desea obtener la division on la fra ion, enton es es ribirlo omo: x = 3.0 / 2;
o x = 3 / 2.0 y aun mejor x = 3.0 / 2.0.

Por otra parte, existe una forma mas orta para expresar al ulos en C. Por ejemplo, si se tienen expresiones
omo: i = i + 3; o x = x * (y + 2); , pueden ser rees ritas omo:
expr1 oper = expr2

Lo ual es equivalente, pero menos e iente que:


expr1 = expr1 oper expr2

Por lo que podemos rees ribir las expresiones anteriores omo: i += 3; y x *= y + 2; respe tivamente.

2.7. Operadores de Compara ion


El operador para probar la igualdad es ==, por lo que se debera tener uidado de no es ribir a identalmente solo
=, ya que:
if ( i = j ) ...

Es una senten ia legal de C (sinta ti amente hablando aunque el ompilador avisa uando se emplea), la ual
opia el valor de \j" en \i", lo ual sera interpretado omo VERDADERO, si j es diferente de ero.
Diferente es !=, otros operadores son: < menor que, > mayor que, <= menor que o igual a y >= (mayor que o igual
a).

2.8. Operadores logi os


Los operadores logi os son usualmente usados on senten ias ondi ionales o rela ionales, los operadores bas ios
logi os son:
&& Y logi o, || O logi o y ! nega ion.

2.9. Orden de pre eden ia


Es ne esario ser uidadosos on el signi ado de expresiones tales omo a + b * , dependiendo de lo que se
desee ha er
(a + b) *

CAPITULO 2. PRINCIPIOS DE C

17

o
a + (b * )

Todos los operadores tienen una prioridad, los operadores de mayor prioridad son evaluados antes que los que
tienen menor prioridad. Los operadores que tienen la misma prioridad son evaluados de izquierda a dere ha, por lo
que:
a - b -

es evaluado omo
(a - b) -

Prioridad

Operador(es)

Mas alta

( ) [ ->
! ~ ++ -- - (tipo) * & sizeof
*/%
+<< >>
< <= > >=
== !=
&
^
|
&&
||
?
= += -= *= /=
,

Mas baja

De a uerdo a lo anterior, la siguiente expresion:


a < 10 && 2 * b <

Es interpretada omo:
(a < 10) && ( (2 * b) < )

y
a =
b =
10 / 5
+ 2;

omo
a =
( b =
( 10 / 5 )
+ 2 );

CAPITULO 2. PRINCIPIOS DE C

18

2.10. Ejer i ios


Es ribir programas en C para ha er las siguientes tareas:
1. Leer la entrada de dos numeros y mostrar el doble produ to del primero menos la mitad del segundo.
2. Lea y es riba su nombre, apellido paterno, apellido materno y matri ula en un formato ade uado.
3. Es ribir un programa para leer un \ otante" que representa un numero de grados Celsius, e imprime omo
un \ otante" la temperatura equivalente en grados Fahrenheit. La salida puede ser de la siguiente forma:
100.0 grados Celsius son 212.0 grados Fahrenheit.

4. Es ribir un programa para imprimir varias ve es el ejer i io 2. Puede usar varias instru iones printf, on
un ara ter de nueva lnea en ada una, o una instru ion on varios ara teres nueva lnea en la adena de
formateo.
5. Es ribir un programa que lea el radio de un r ulo omo un numero otante y muestre el area y el permetro
del r ulo.
6. Dados iertos entmetros omo entrada de tipo otante, imprimir su equivalen ia a pies (enteros) y pulgadas
( otante, 1 de imal), dando las pulgadas on una pre ision de un lugar de imal Suponer 2.54 entmetros por
pulgada, y 12 pulgadas por pie.
Si la entrada es 333.3, el formato de la salida debera ser:
333.3 entmetros son 10 pies 11.2 pulgadas.

Cap
tulo 3

Estru turas Condi ionales


En este aptulo se revisan los distintos metodos on los que C ontrola el ujo logi o de un programa.
Como se reviso en el aptulo anterior, los operadores rela iones binarios que se usan son:
==, !=, <, <=, > y >=

ademas los operadores logi os binarios:


||, &&

y el operador logi o unario de nega ion !, que solo toma un argumento.


Los operadores anterior son usados on las siguientes estru turas que se muestran.

3.1. La senten ia if
Las tres formas omo se puede emplear la senten ia if son:

if ( ondi ion)
senten ia;

...o

if ( ondi ion)
senten ia1 ;
else
senten ia2 ;

...o

if ( ondi ion1 )

19

CAPITULO 3. ESTRUCTURAS CONDICIONALES

20

senten ia1 ;
else if ( ondi ion2 )
senten ia2 ;

...
else
senten ian ;

El ujo logi o de esta estru tura es de arriba ha ia abajo. La primera senten ia se eje utara y se saldra de la
estru tura if si la primera ondi ion es verdadera. Si la primera ondi ion fue falsa, y existe otra ondi ion, se
evalua, y si la ondi ion es verdadera, enton es se eje uta la senten ia aso iada. Si existen mas ondi iones dentro
de la estru tura if, se van evaluando estas, siempre y uando las ondi iones que le pre edan sean falsas.
La senten ia que esta aso iada a la palabra reservada else, se eje uta si todas las ondi iones de la estru tura
if fueron falsas.
Por ejemplo:
main()
{
int x, y, w;
........
if (x>0)
{
z=w;
.......
}
else
{
z=y;
.......
}
}

3.2. El operador ?
El operador ternario ondi ional ? es mas e iente que la senten ia if. El operador ? tiene el siguiente formato:
expresion1 ? expresion 2 : expresion3 ;

Que es equivalente a la siguiente expresion:


if (expresion1 ) then expresion2 else expresion3 ;

Por ejemplo, para asignar el maximo de a y b a la variable z, usando ?, tendramos:


z = (a>b) ? a : b;

CAPITULO 3. ESTRUCTURAS CONDICIONALES

21

que es lo mismo que:


if (a > b)
z = a;
else
z = b;

El uso del operador ? para reemplazar las senten ias if ... else no se restringe solo a asigna iones, omo en
el ejemplo anterior. Se pueden eje utar una o mas llamadas de fun ion usando el operador ? poniendolas en las
expresiones que forman los operandos, omo en el ejemplo siguiente:
f1(int n)
{
printf("%d ",n);
}
f2()
{
printf("introdu ido\n");
}
main()
{
int t;
printf(": ");
s anf("%d",&t);
/* imprime mensaje apropiado */
t ? f1(t) + f2() : printf("Cero introdu ido\n");
}

3.3. La senten ia swit h


Aunque on la estru tura if ... else if se pueden realizar omproba iones multiples, en o asiones no es muy
elegante, ya que el odigo puede ser dif il de seguir y puede onfundir in luso al autor pasado el tiempo. Por lo anterior, C tiene in orporada una senten ia de bifur a ion multiple llamada swit h. Con esta senten ia, la omputadora
omprueba una variable su esivamente frente a una lista de onstantes enteras o de ara ter. Despues de en ontrar
una oin iden ia, la omputadora eje uta la senten ia o bloque de senten ias que se aso ian on la onstante. La
forma general de la senten ia swit h es:

swit h (variable)

ase onstante1 :
se uen ia de senten ias

break;

CAPITULO 3. ESTRUCTURAS CONDICIONALES

22

ase onstante2 :
se uen ia de senten ias

break;

ase onstante3 :
se uen ia de senten ias

break;
...
default:

se uen ia de senten ias

g
donde la omputadora eje uta la senten ia default si no oin ide ninguna onstante on la variable. Esta ultima
op ion es op ional. Cuando se en uentra una oin iden ia, la omputadora eje uta las senten ias aso iadas on el
ase hasta en ontrar un break, o hasta el nal de la senten ia swit h en aso de que se emplee default o sea el
ultimo ase.
Las limita iones que tiene la senten ia ase respe to a la estru tura if son:
Con swit h solo se puede omprobar por igualdad, mientras que on if puede ser on ualquier operador
rela ional.
No se pueden tener dos onstantes en un solo ase.
La forma omo se puede simular el ultimo punto, es teniendo una senten ia nula in luyendo solo un ; o permitiendo
que la senten ia swit h aiga omitiendo las senten ias omo se muestra a ontinua ion.
swit h (letra)
{
ase 'a':
ase 'e':
ase 'i':
ase 'o':
ase 'u':
numvo ales++;
break;
ase ' ':
numesp++;
break;
default:
numotras++;
break;
}

CAPITULO 3. ESTRUCTURAS CONDICIONALES

23

3.4. Ejer i ios


1. Es ribir un programa que lea dos ara teres, e imprima su valor uando se pueda interpretar omo un numero
hexade imal. A eptar letras mayus ulas y minus ulas para los valores del 10 al 15.
2. Leer un valor entero. Suponer que el numero es un da de la semana. Suponer que 0 orresponde a Domingo y
as su esivamente. Imprimir el nombre del da.
3. Dados omo entrada 3 enteros representando la fe ha omo da, mes, a~no, imprimir la fe ha del da anterior.
Por ejemplo para una entrada omo: 1 3 1992 La salida sera: Fe ha anterior a 1-3-1992 es 29-02-1992
4. Es ribir un programa el ual lea dos valores enteros. Si el primero es menor que el segundo, que imprima el
mensaje \Arriba". Si el segundo es menor que el primero, que imprima el mensaje \Abajo". Si los numeros son
iguales, que imprima el mensaje \igual". Si hay un error en la le tura de los datos, que imprima un mensaje
onteniendo la palabra \Error" y haga exit( 0 );

Cap
tulo 4

Itera i
on
En este aptulo se revisan los me anismos de C para repetir un ojunto de instru iones hasta que se umple
ierta ondi ion.

4.1. La senten ia for


La senten ia for tiene el siguiente formato:

for (

expresion1 ; expresion2 ; expresion3 )

senten ia;
o f bloque de senten ias

En donde expresion1 se usa para realizar la ini ializa ion de variables, usando una o varias senten ias, si se
usan varias senten ias debera usarse el operador , para separarlas. Por lo general, estable e el valor de la variable de
ontrol del i lo. expresion2 se usa para la ondi ion de termina ion del i lo y expresion3 es el modi ador a la
variable de ontrol del i lo ada vez que la omputadora lo repite, pero tambien puede ser mas que un in remento.
Por ejemplo:
int X;
main()
{
for( X=3; X>0; X--)
{
printf("X=%d\n",X);
}
}

genera la siguiente salida a pantalla . . .


X=3
X=2
X=1

Todos las siguientes senten ias for son validas en C. Las apli a iones pra ti as de tales senten ias no son importantes aqu, ya que tan solo se intenta ilustrar alguanas ara tersti as que pueden ser de utilidad:
24


CAPITULO 4. ITERACION

25

for ( x=0; ( (x>3) && (x<9) ); x++ )


for ( x=0, y=4; ( (x>3) && (x<9) ); x++, y+=2)
for ( x=0, y=4, z=4000; z; z/=10)

En el segundo ejemplo se muestra la forma omo multiples expresiones pueden apare er, siempre y uando esten
separadas por una oma ,
En el ter er ejemplo, el i lo ontinuara iterando hasta que z se onvierta en 0.

4.2. La senten ia while


La senten ia while es otro i lo o bu le disponible en C. Su formato es:

while (

expresion) senten ia;

donde senten ia puede ser una senten ia va a, una senten ia uni a o un bloque de senten ias que se repetiran.
Cuando el ujo del programa llega a esta instru ion, primero se revisa si la ondi ion es verdad para eje utar la(s)
senten ia(s), y despues el i lo while se repetira mientras la ondi ion sea verdadera. Cuando llega a ser falsa, el
ontrol del programa pasa a la lnea que sigue al i lo.
En el siguiente ejemplo se muetra una rutina de entrada desde el te lado, la ual se i la mientras no se pulse A:
main()
{
har ara ;
ara = '\0';
while( ara != 'A') ara = get har();
}

Antes de entrar al i lo se ini ializa la variable ara a nulo. Despues pasa a la senten ia while donde se omprueba
si ara no es igual a 'A', omo sea verdad enton es se eje uta la senten ia del bu le ( ara = get har();). La
fun ion get har() lee el siguiente ara ter del ujo estandar (te lado) y lo devuelve, que en nuestro ejemplo es el
ara ter que haya sido te leado. Una vez que se ha pulsado una te la, se asigna a ara y se omprueba la ondi ion
nuevamente. Despues de pulsar A, la ondi ion llega a ser falsa porque ara es igual a A, on lo que el i lo termina.
De lo anterior, se tiene que tanto el i lo for, omo el i lo while omprueban la ondi ion en lo alto del i lo,
por lo que el odigo dentro del i lo no se eje uta siempre.
A ontinua ion mostramos otro ejemplo:
main()
{
int x=3;
while( x>0 )
{
printf("x = %d\n", x);
x--;


CAPITULO 4. ITERACION

26

}
}

que genera la siguiente salida en pantalla:


x = 3
x = 2
x = 1

Como se observa, dentro del i lo tenemos mas de una senten ia, por lo que se requiere usar la llave abierta y la
llave errada { ... } para que el grupo de senten ias sean tratadas omo una unidad.
Como el i lo while pueda a eptar tambien expresiones, y no solamente ondi iones lo siguiente es valido:
while ( x-- );
while ( x = x + 1 );
while ( x += 5 );

Si se usan este tipo de expresiones, solamente uando el resultado de x--, x=x+1 o x+=5 sea ero, la ondi ion
fallara y se podra salir del i lo.
De a uerdo a lo anterior, podemos realizar una opera ion ompleta dentro de la expresion. Por ejemplo:
main()
{
har ara ;
ara = '\0';
while ( ( ara = get har()) != 'A' )
put har( ara );
}

En este ejemplo se usan las fun iones de la bibliote a estandar get har() | lee un ara ter del te lado y
put har() es ribe un ara ter dado en pantalla. El i lo while pro edera a leer del te lado y lo mostrara hasta que

el ara ter A sea ledo.

4.3. La senten ia do-while


Al ontrario de los i los for y while que omprueban la ondi ion en lo alto del bu le, el bu le do ... while
la examina en la parte baja del mismo. Esta ara tersti a provo a que un i lo do ... while siempre se eje ute al
menos una vez. La forma general del i lo es:

do

f
senten ia;

while ( ondi i
on);


CAPITULO 4. ITERACION

27

Aunque no son ne esarias las llaves uando solo esta presente una senten ia, se usan normalmente por legibilidad
y para evitar onfusion (respe to al le tor, y no del ompilador) on la senten ia while.
En el siguiente programa se usa un i lo do ... while para leer numeros desde el te lado hasta que uno de ellos
es menor que o igual a 100:
main()
{
int num;
do
{
s anf("%d", &num);
} while ( num>100 );
}

Otro uso omun de la estru tura do ... while es una rutina de sele ion en un menu, ya que siempre se requiere
que se eje ute al menos una vez.
main()
{
int op ;
printf("1. Derivadas\n");
printf("2. Limites\n");
printf("3. Integrales\n");
do
{
printf(" Te lear una op ion: ");
s anf("%d", &op );
swit h(op )
{
ase 1:
printf("\tOp ion 1 sele ionada\n\n");
break;
ase 2:
printf("\tOp ion 2 sele ionada\n\n");
break;
ase 3:
printf("\tOp ion 3 sele ionada\n\n");
break;
default:
printf("\tOp ion no disponible\n\n");
break;
}
} while( op != 1 && op != 2 && op != 3);
}


CAPITULO 4. ITERACION

28

Se muestra un ejemplo donde se rees ribe usando do ... while uno de los ejemplos ya mostrados.
main()
{
int x=3;
do
{
printf("x = %d\n", x--);
}
while( x>0 ) ;
}

4.4. Uso de break y ontinue


Como se omento uno de los usos de la senten ia break es terminar un ase en la senten ia swit h. Otro uso es
forzar la termina ion inmediate de un i lo, saltando la prueba ondi ional del i lo.
Cuando se en uentra la senten ia break en un bu le, la omputadora termina inmediatamente el i lo y el ontrol
del programa pasa a la siguiente sente ia del i lo. Por ejemplo:
main()
{
int t;
for(t=0; t<100; t++)
{
printf("%d ", t);
if (t==10) break;
}
}

Este programa muestra en pantalla los numeros del 0 al 10, uando al anza el valor 10 se umple la ondi ion de
la senten ia if, se eje uta la senten ia break y sale del i lo.
La senten ia ontinue fun iona de manera similar a la senten ia break. Sin embargo, en vez de forzar la salida,
ontinue fuerza la siguiente itera ion, por lo que salta el odigo que falta para llegar a probar la ondi ion. Por
ejemplo, el siguiente programa visualizara solo los numeros pares:
main()
{
int x;
for( x=0; x<100; x++)
{
if (x%2)
ontinue;
printf("%d ",x);
}
}

Finalmente se onsidera el siguiente ejemplo donde se leen valores enteros y se pro esan de a uerdo a las siguientes
ondi iones. Si el valor que sea ledo es negativo, se desea imprimir un mensaje de error y se abandona el i lo. Si el
valor es mayor que 100, se ignora y se ontinua leyendo, y si el valor es ero, se desea terminar el i lo.


CAPITULO 4. ITERACION

29

main()
{
int valor;
while( s anf("%d", &valor) == 1 && valor != 0)
{
if ( valor<0 )
{
printf("Valor no valido\n");
break;
/* Salir del i lo */
}
if ( valor>100)
{
printf("Valor no valido\n");
ontinue;
/* Pasar al prin ipio del i lo nuevamente */
}
printf("Se garantiza que el valor leido esta entre 1 y 100");
}
}

4.5. Ejer i ios


1. Es ribir un programa que lea 5 numeros y en uentre el promedio, el maximo y el mnimo de esos valores.
2. Es ribir un programa que lea numeros hasta que se en uentre el ero. El segundo numero se sumara al primero,
luego el ter ero se restara, el uarto se sumara, y as se debera seguir alternado hasta que se llegue al ero.
Cuando se llegue a esta ondi ion debera imprimir el resultado, el total de operandos de la opera ion (sin
in luir el ero), y la suma de los operandos que se restaron.
3. Es ribir un programa que lea un valor entero que sera la base para un sistema numeri o (binario, o tal o
de imal), despues que lea un entero positivo en esa base y que imprima su valor en base 10. Se debe validar que
el numero pertenez a a esa base. La base sera menor que o igual a 10. El programa podra tener la siguiente
salida:
Entrada
Base Numero
==============
10
1234
8
77
2
1111

Salida
=========
1234
63
15

4. Es ribir un programa que lea un numero en base 10 y lo onvierta a base 2, base 8 y base hexade imal.
5. Leer tres valores representando lo siguiente:
El apital (numero entero de pesos)


CAPITULO 4. ITERACION

30

Una tasa de interes en por iento ( otante)


y un numero de a~nos (entero).
Cal ular los valores de la suma del apital y el interes ompuesto para un perodo dado de a~nos. Para ada a~no
el interes es al ulado omo: interes = apital * tasa_interes / 100;
el ual se suma al apital
apital += interes;

Imprimir los valores de moneda on una pre ision de dos de imales. Imprimir los valores del interes ompuesto
para ada a~no al nal del perodo. La salida puede ser omo la siguiente:
Capital ini ial 35000.00 on tasa del 12.50 en 10 a~
nos
A~no
Interes
Suma
-----+-----------+--------1 4375.00
39375.00
2 4921.88
44296.88
3 5537.11
49833.98
4 6229.25
56063.23
5 7007.90
63071.14
6 7883.89
70955.03
7 8869.38
79824.41
8 9978.05
89802.45
9 11225.31 101027.76
10 12628.47 113656.23

6. Leer un valor positivo, y ha er la siguiente se uen ia: si el numero es par, dividirlo entre 2; si es non, multipli arlo por 3 y sumarle 1. Repetir lo anterior hasta que el valor sea 1, imprimiendo ada valor, tambien se
debera imprimir uantas opera iones de estas son he has.
Una salida podra ser la siguiente:
El valor ini ial es 9
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
Valor fina1 1, numero

28
14
7
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
de pasos 19.


CAPITULO 4. ITERACION

31

Si el valor ingresado es menor que 1, imprimir un mensaje que ontenga la palabra


Error

y haga
exit(0)

Cap
tulo 5

Arreglos y adenas
En el siguiente aptulo se presentan los arreglos y las adenas. Las adenas se onsideran omo un arreglo de
tipo har.

5.1. Arreglos unidimensionales y multidimensionales


Los arreglos son una ole ion de variables del mismo tipo que se referen ian utilizando un nombre omun. Un
arreglo onsta de posi iones de memoria ontigua. La dire ion mas baja orresponde al primer elemento y la mas
alta al ultimo. Un arreglo puede tener una o varias dimensiones. Para a eder a un elemento en parti ular de un
arreglo se usa un ndi e.
El formato para de larar un arreglo unidimensional es:
tipo nombre arr [

tama~no

Por ejemplo, para de larar un arreglo de enteros llamado listanum on diez elementos se ha e de la siguiente
forma:
int listanum[10;

En C, todos los arreglos usan ero omo ndi e para el primer elemento. Por tanto, el ejemplo anterior de lara un
arreglo de enteros on diez elementos desde listanum[0 hasta listanum[9.
La forma omo pueden ser a esados los elementos de un arreglo, es de la siguiente forma:
listanum[2 = 15; /* Asigna 15 al 3er elemento del arreglo listanum*/
num = listanum[2; /* Asigna el ontenido del 3er elemento a la variable num */

El lenguaje C no realiza omproba ion de ontornos en los arreglos. En el aso de que sobrepase el nal durante
una opera ion de asigna ion, enton es se asignaran valores a otra variable o a un trozo del odigo, esto es, si se
dimensiona un arreglo de tama~no N, se puede referen iar el arreglo por en ima de N sin provo ar ningun mensaje de
error en tiempo de ompila ion o eje u ion, in luso aunque probablemente se provoque el fallo del programa. Como
programador se es responsable de asegurar que todos los arreglos sean lo su ientemente grandes para guardar lo
que pondra en ellos el programa.
C permite arreglos on mas de una dimension , el formato general es:
tipo nombre arr [

tam1 [ tam2 ... [ tamN;

Por ejemplo un arreglo de enteros bidimensionales se es ribira omo:


int tabladenums[50[50;

32

CAPITULO 5. ARREGLOS Y CADENAS

33

Observar que para de larar ada dimension lleva sus propios parentesis uadrados.
Para a eder los elementos se pro ede de forma similar al ejemplo del arreglo unidimensional, esto es,
tabladenums[2[3 = 15; /* Asigna 15 al elemento de la 3a fila y la 4a olumna*/
num = tabladenums[25[16;

A ontinua ion se muestra un ejemplo que asigna al primer elemento de un arreglo bidimensional ero, al siguiente
1, y as su esivamente.
main()
{
int t,i,num[3[4;
for(t=0; t<3; ++t)
for(i=0; i<4; ++i)
num[t[i=(t*4)+i*1;
for(t=0; t<3; ++t)
{
for(i=0; i<4; ++i)
printf("num[%d[%d=%d ", t,i,num[t[i);
printf("\n");
}
}

En C se permite la ini ializa ion de arreglos, debiendo seguir el siguiente formato:


tipo nombre arr[ tam1 [

tam2 ... [ tamN = flista-valoresg;

Por ejemplo:
int i[10 = {1,2,3,4,5,6,7,8,9,10};
int num[3[4={0,1,2,3,4,5,6,7,8,9,10,11};

5.2. Cadenas
A diferen ia de otros lenguajes de programa ion que emplean un tipo denominado adena string para manipular
un onjunto de simbolos, en C, se debe simular mediante un arreglo de ara teres, en donde la termina ion de la
adena se debe indi ar on nulo. Un nulo se espe i a omo '\0'. Por lo anterior, uando se de lare un arreglo de
ara teres se debe onsiderar un ara ter adi ional a la adena mas larga que se vaya a guardar. Por ejemplo, si se
quiere de larar un arreglo adena que guarde una adena de diez ara teres, se hara omo:
har adena[11;

Se pueden ha er tambien ini ializa iones de arreglos de ara teres en donde automati amente C asigna el ara ter
nulo al nal de la adena, de la siguiente forma:
har nombre arr[ tam = adena";

Por ejemplo, el siguiente fragmento ini ializa adena on \hola":


har adena[5="hola";

CAPITULO 5. ARREGLOS Y CADENAS

34

El odigo anterior es equivalente a:


har adena[5={'h','o','l','a','\0'};

Para asignar la entrada estandar a una adena se puede usar la fun ion s anf on la op ion %s (observar que no
se requiere usar el operador &), de igual forma para mostrarlo en la salida estandar.
Por ejemplo:
main()
{
har nombre[15, apellidos[30;
printf("Introdu e tu nombre: ");
s anf("%s",nombre);
printf("Introdu e tus apellidos: ");
s anf("%s",apellidos);
printf("Usted es %s %s\n",nombre,apellidos);
}

El lenguaje C no maneja adenas de ara teres, omo se ha e on enteros o otantes, por lo que lo siguiente no
es valido:
main()
{
har nombre[40, apellidos[40, ompleto[80;
nombre="Jose Mara";
/* Ilegal */
apellidos="Morelos y Pav
on";
/* Ilegal */
ompleto="Gral."+nombre+appellidos; /* Ilegal */
}

5.3. Ejer i ios


1. Es ribir un programa que lea un arreglo de ualquier tipo (entero, otante, har), se podra pedir al usuario
que indique el tipo de arreglo, y tambien es ribir un programa que revise el arreglo para en ontrar un valor en
parti ular.
2. Leer un texto, un ara ter a la vez desde la entrada estandar (que es el te lado), e imprimir ada lnea en forma
invertida. Leer hasta que se en uentre un nal-de-datos (te lar CONTROL-D para generarlo).
El programa podra probarse te leando progrev | progrev para ver si una opia exa ta de la entrada original
es re reada.
Para leer ara teres hasta el nal de datos, se puede usar un i lo omo el siguiente
har h;
while( h=get har(), h>=0 ) /* h < 0 indi a fin-de-datos */

o
har h;
while( s anf( "% ", & h ) == 1 ) /* se lee un ara ter */

CAPITULO 5. ARREGLOS Y CADENAS

35

3. Es ribir un programa para leer un texto hasta el n-de-datos, y mostrar una estadsti a de las longitudes de
las palabras, esto es, el numero total de palabras de longitud 1 que hayan o urrido, el total de longitud 2 y
as su esivamente.
De ne una palabra omo una se uen ia de ara teres alfabeti os. Se deberan permitir palabras hasta de una
longitud de 25 letras.
Una salida tpi a podra ser omo esta:
longitud
longitud
longitud
longitud
longitud

1 : 16 o urren ias
2 : 20 o urren ias
3 : 5 o urren ias
4 : 2 o urren ias
5 : 0 o urren ias
........

Cap
tulo 6

Fun iones
Una fun ion es un onjunto de de lara iones, de ni iones, expresiones y senten ias que realizan una tarea espe  a.
El formato general de una fun ion en C es

espe ifi ador de tipo nombre de fun ion( lista

de parametros )

variables lo ales
odigo de la fun ion

g
El espe i ador de tipo indi a el tipo del valor que la fun ion devolvera mediante el uso de return. El valor puede
ser de ualquier tipo valido. Si no se espe  a un valor, enton es la omputadora asume por defe to que la fun ion
devolvera un resultado entero. No se tienen siempre que in luir parametros en una fun ion. la lista de parametros
puede estar va a.
Las fun iones terminan y regresan automati amente al pro edimiento que las llamo uando se en uentra la ultima
llave }, o bien, se puede forzar el regreso antes usando la senten ia return. Ademas del uso se~nalado la fun ion return
se usa para devolver un valor.
Se examina a ontinua ion un ejemplo que en uentra el promedio de dos enteros:
float en ontprom(int num1, int num2)
{
float promedio;
promedio = (num1 + num2) / 2.0;
return(promedio);
}
main()
{
int a=7, b=10;
float resultado;
resultado = en ontprom(a, b);

36

CAPITULO 6. FUNCIONES

37

printf("Promedio=%f\n",resultado);
}

6.1. Fun iones void


Las fun iones void dan una forma de emular, lo que en otros lenguajes se ono en omo pro edimientos (por
ejemplo, en PASCAL). Se usan uando no requiere regresar un valor. Se muestra un ejemplo que imprime los
uadrados de iertos numeros.
void uadrados()
{
int ontador;
for( ontador=1; ontador<10; ontador++)
printf("%d\n", ontador* ontador);
}
main()
{
uadrados();
}

En la fun ion uadrados no esta de nido ningun parametro, y por otra parte tampo o se emplea la senten ia
return para regresar de la fun ion.

6.2. Fun iones y arreglos


Cuando se usan un arreglo omo un argumento a la fun ion, se pasa solo la dire ion del arreglo y no la opia del
arreglo entero. Para nes pra ti os podemos onsiderar el nombre del arreglo sin ningun ndi e omo la dire ion del
arreglo.
Considerar el siguiente ejemplo en donde se pasa un arreglo a la fun ion imp_rev, observar que no es ne esario
espe i ar la dimension del arreglo uando es un parametro de la fun ion.
void imp_rev( har s[)
{
int t;
for( t=strlen(s)-1; t>=0; t--)
printf("% ",s[t);
}
main()
{
har nombre[="Fa ultad";
imp_rev(nombre);
}

CAPITULO 6. FUNCIONES

38

Observar que en la fun ion imp_rev se usa la fun ion strlen para al ular la longitud de la adena sin in luir el
terminador nulo. Por otra parte, la fun ion imp_rev no usa la senten ia return ni para terminar de usar la fun ion,
ni para regresar algun valor.
Se muestra otro ejemplo,
float en onprom(int tam, float lista[)
{
int i;
float suma = 0.0;
for ( i=0; i<tam; i++)
suma += lista[i;
return(suma/tam);
}
main()
{
float numeros[={2.3, 8.0, 15.0, 20.2, 44.01, -3.0, -2.9};
printf("El promedio de la lista es %f\n", en onprom(7,numeros) );
}

Para el aso de que se tenga que pasar un arreglo on mas de una dimension, no se indi a la primera dimension
pero, el resto de las dimensiones deben se~nalarse. Se muestra a ontinua ion un ejemplo:
void imprtabla(int tamx,int tamy, float tabla[[5)
{
int x,y;
for ( x=0; x<tamx; x++ )
{
for ( y=0; y<tamy; y++ )
printf("t[%d[%d=%f",x,y,tabla[x[y);
printf("\n");
}
}

6.3. Prototipos de fun iones


Antes de usar una fun ion C debe tener ono imiento a er a del tipo de dato que regresara y el tipo de los
parametros que la fun ion espera.
El estandar ANSI de C introdujo una nueva (mejor) forma de ha er lo anterior respe to a las versiones previas
de C.
La importan ia de usar prototipos de fun iones es la siguiente:
Se ha e el odigo mas estru turado y por lo tanto, mas fa il de leer.
Se permite al ompilador de C revisar la sintaxis de las fun iones llamadas.
Lo anterior es he ho, dependiendo del al an e de la fun ion. Basi amente si una fun ion ha sido de nida antes
de que sea usada (o llamada), enton es se puede usar la fun ion sin problemas.

CAPITULO 6. FUNCIONES

39

Si no es as, enton es la fun ion se debe de larar. La de lara ion simplemente maneja el tipo de dato que la
fun ion regresa y el tipo de paro ametros usados por la fun ion.
Es una pra ti a usual y onveniente es ribir el prototipo de todas las fun iones al prin ipio del programa, sin
embargo esto no es estri tamente ne esario.
Para de larar un prototipo de una fun ion se indi ara el tipo de dato que regresara la fun ion, el nombre de la
fun ion y entre parentesis la lista del tipo de los parametros de a uerdo al orden que apare en en la de ni ion de la
fun ion. Por ejemplo:
int long ad( har [);

Lo anterior de lara una fun ion llamada long ad que regresa un valor entero y a epta una adena omo parametro.

6.4. Ejer i ios


1. Es ribir una fun ion \reemplaza", la ual toma una adena omo parametro, le reemplaza todos los espa ios
de la adena por un guion bajo, y devuelve el numero de espa ios reemplazados. Por ejemplo:
har adena[ = "El gato negro";
n = reemplaza( adena );

debera devolver:
adena onvertida "El_gato_negro"
n = 2

2. Es ribir un programa que lea una lnea de texto en un bu er (una adena de ara teres) usando la fun ion
gets y al ule la longitud de la lnea (NO usar la fun ion strlen).
3. Modi ar el programa anterior para que lea un ar hivo de texto. El ar hivo debera redire ionarse al programa,
debiendo mostrar el ontenido del mismo. En aso de que se lea una lnea on longitud 0 debera terminar el
programa.

Cap
tulo 7

Mas tipos de datos


En este aptulo se revisa la forma omo pueden ser reados y usados en C tipos de datos mas omplejos y
estru turas.

7.1. Estru turas


En C una estru tura es una ole ion de variables que se referen ian bajo el mismo nombre. Una estru tura
propor iona un medio onveniente para mantener junta informa ion que se rela iona. Una de ni ion de estru tura
forma una plantilla que se puede usar para rear variables de estru tura. Las variables que forman la estru tura son
llamados elementos estru turados.
Generalmente, todos los elementos en la estru tura estan rela ionados logi amente unos on otros. Por ejemplo,
se puede representar una lista de nombres de orreo en una estru tura. Mediante la palabra lave stru t se le indi a
al ompilador que de na una plantilla de estru tura.
stru t dire
{
har nombre[30;
har alle[40;
har iudad[20;
har estado[3;
unsigned int odigo;
};

Con el trozo de odigo anterior no ha sido de larada ninguna variable, tan solo se ha de nido el formato.
Para de larar una variable, se hara omo sigue:
stru t dire info_dire ;

Se pueden de larar una o mas variables uando se de ne una estru tura entre ) y ;. Por ejemplo:
stru t dire
{
har nombre[30;
har alle[40;
har iudad[20;
har estado[3;
unsigned int odigo;

40

 TIPOS DE DATOS
CAPITULO 7. MAS

41

} info_dire , binfo, info;

observar que dire es una etiqueta para la estru tura que sirve omo una forma breve para futuras
de lara iones. Como en este ultima de lara ion se indi an las variables on esta estru tura, se puede
omitir el nombre de la estru tura tipo.
Las estru turas pueden ser tambien preini ializadas en la de lara ion:
stru t dire info_dire ={"Vi ente Fernandez","Fantasia 2000","Dorado","MMX",12345};

Para referen iar o a esar un miembro (o ampo) de una estru tura, C propor iona el operador punto ., por
ejemplo, para asignar a info_dire otro odigo, lo ha emos omo:
info_dire . odigo=54321;

7.1.1. De ni ion de nuevos tipos de datos


Se se~nalo (se ion ??) previamente que typedef se puede usar para de nir nuevos nombres de datos expli tamente,
usando algunos de los tipos de datos de C, donde su formato es:

typedef <tipo><nombre>;
Se puede usar typedef para rear nombres para tipos mas omplejos, omo una estru tura, por ejemplo:
typedef stru t dire
{
har nombre[30;
har alle[40;
har iudad[20;
har estado[3;
unsigned int odigo;
} sdire ;
sdire info_dire ={"Vi ente Fernandez","Fantasia 2000","Dorado","MMX",12345};

en este aso dire sirve omo una etiqueta a la estru tura y es op ional, ya que ha sido de nido un nuevo
tipo de dato, por lo que la etiqueta no tiene mu ho uso, en donde sdire es el nuevo tipo de datos e
info_dire es una variable del tipo sdire , la ual es una estru tura.
Con C tambien se pueden tener arreglos de estru turas:
typedef stru t dire
{
har nombre[30;
har alle[40;
har iudad[20;
har estado[3;
unsigned int odigo;
} info_dire ;
info_dire artistas[1000;

por lo anterior, artistas tiene 1000 elementos del tipo info_dire . Lo anterior podra ser a esado de
la siguiente forma:

 TIPOS DE DATOS
CAPITULO 7. MAS

42

artistas[50. odigo=22222;

7.2. Uniones
Una union es una variable la ual podra guardar (en momentos diferentes) objetos de diferentes tama~nos y tipos.
C emplea la senten ia union para rear uniones por ejemplo:
union numero
{
short shortnumero;
long longnumero;
double floatnumero;
} unumero;

on lo anterior se de ne una union llamada numero y una instan ia de esta llamada unumero. numero es
la etiqueta de la union y tiene el mismo omportamiento que la etiqueta en la estru tura.
Los miembros pueden ser a esados de la siguiente forma:
printf("%ld\n",unumero.longnumero);

on la llamada a la fun ion se muestra el valor de longnumero.


Cuando el ompilador de C esta reservando memoria para las uniones, siempre reara una variable lo su ientemente grande para que quepa el tipo de variable mas largo de la union.
Con la nalidad de que el programa pueda llevar el registro del tipo de la variable union usada en un momento
dado, es omun tener una estru tura ( on una union anidada) y una variable que indi a el tipo de union.
Se muestra un ejemplo de lo anterior:
typedef stru t
{
int maxpasajeros;
} jet;
typedef stru t
{
int apa _elev;
} heli optero;
typedef stru t
{
int max arga;
} avion arga;
typedef union
{
jet jetu;
heli optero heli opterou;
avion arga avion argau;
} transporteaereo;

 TIPOS DE DATOS
CAPITULO 7. MAS

43

typedef stru t
{
int tipo;
int velo idad;
transporteaereo des rip ion;
} un_transporteaereo

en el ejemplo se de ne una union base de transporte aereo el ual puede ser un jet, un heli optero o un
avion de arga.
En la estru tura un_transporeaereo hay un miembro para el tipo, que indi a ual es la estru tura manejada en
ese momento.

7.3. Conversion de tipos ( asts)


C es uno de los po os lenguajes que permiten la onversion de tipos, esto es, forzar una variable de un tipo a ser
de otro tipo. Lo anterior se presenta uando variables de un tipo se mez lan on las de otro tipo. Para llevar a abo
lo anterior se usa el operador de onversion ( ast) (). Por ejemplo:
int numeroentero;
float numeroflotante = 9.87;
numeroentero = (int) numeroflotante;

on lo ual se asigna 9 a la variable numeroentero y la fra ion es dese hada.


El siguiente odigo:
int numeroentero = 10;
float numeroflotante;
numeroflotante = (float) numeroentero;

asigna 10.0 a numeroflotante. Como se observa C onvierte el valor del lado dere ho de la asigna ion
al tipo del lado izquierdo.
La onversion de tipos puede ser tambien usada on ualquier tipo simple de datos in luyendo har, por lo tanto:
int numeroentero;
har letra = 'A';
numeroentero = (int) letra;

 a numeroentero.
asigna 65 (que es el odigo ASCII de A')
Algunas onversiones de tipos son he has automati amente { esto es prin ipalmente por la ara tersti a de
ompatibilidad de tipos.
Una buena regla es la siguiente: En aso de duda, onversion de tipos.
Otro uso es asegurarse que la division de numeros se omporta omo se requiere, ya que si se tienen dos enteros
la forma de forzar el resultado a un numero otante es:
numeroflotante = (float) numerent / (float) denoment;

on lo que se asegura que la division devolvera un numero otante.

 TIPOS DE DATOS
CAPITULO 7. MAS

44

7.4. Enumera iones


Una enumera ion es un onjunto de onstantes enteras on nombre y espe i a todos los valores legales que puede
tener una variable del tipo enum.
La forma omo se de ne una enumera ion es de forma pare ida a omo se ha e on las estru turas, usando la
palabra lave enum para el omienzo de un tipo de enumera ion. Su formato es:
enum

nombre enum f lista de enumera ion g lista de variables;

Es op ional nombre enum y lista de variables. La primera se usa para de larar las variables de su tipo. El
siguiente fragmento de ne una enumera ion llamada dis o que de lara alma enamiento para ser de ese tipo.
enum alma enamiento { diskette, dd, d, dvd, inta };
enum alma enamiento dis o;

Con la siguiente de ni ion y de lara ion son validas las siguientes senten ias:
dis o = d;
if ( dis o == diskette )
printf("Es de 1440 Kb\n");

Se ini ializa el primer smbolo de enumera ion a ero, el valor del segundo smbolo a 1 y as su esivamente, a
menos que se ini iali e de otra manera. Por tanto,
printf("%d %d\n", dd, inta)

muestra 1 4 en la pantalla.
Se puede espe i ar el valor de uno o mas smbolos usando un ini ializador. Para ha erlo, poner un signo igual y
un valor entero despues del smbolo.
Por ejemplo, lo siguiente asigna el valor 250 a d
enum dis o { diskette, duro, d=250, dvd, inta };

Por lo tanto los valores de los smbolos son los siguientes:

diskette
duro
d
dvd
inta

0
1
250
251
252

7.5. Variables estati as


C soporta uatro espe i adores de lase de alma enamiento. Son

auto
extern
stati
register
Estos espe if adores le di en al ompilador omo alma enar la variable que sigue. El espe i ador de alma enamiento pre ede a la de lara ion de variable que tiene el formato general:

 TIPOS DE DATOS
CAPITULO 7. MAS

45

espe if alma espe if tipo lista variables;


Se usa el espe i ador auto para de larar variables lo ales. Sin embargo, raramente se usa porque las variables
lo ales son auto por defe to.
Las variables stati son variables permanentes en su propia fun ion o ar hivo. Se diferen ian de las variables
globales porque son des ono idas fuera de sus fun iones o ar hivo, pero mantienen sus valores entre llamadas. Esta
ara tersti a las ha e utiles uando se es riben fun iones generales y bibliote as de fun iones.
Variables stati lo ales. Una variable estati a lo al es una variable lo al que retienen su valor entre llamadas de
fun ion, ya que C les rea un alma enamiento permanente. Si lo anterior no se pudiera ha er, enton es se tendran que
usar variables globales {que abrira la puerta a posibles efe tos laterales{. Un ejemplo de una fun ion que requerira
tales variables es un generador de series de numeros que produ e un numero nuevo basado en el ultimo.
A ontinua ion se muestra un ejemplo en donde se analiza el omportamiento de una variable auto y una variable

stati

void stat();

/* Prototipo de la fun ion */

main()
{
int i;
for (i=0; i<5; ++i)
stat();
}
void stat()
{
auto int a_var = 0;
stati int s_var = 0;
printf("auto = %d, stati = %d \n", a_var, s_var);
++a_var;
++s_var;
}

La salida del odigo anterior es:


auto
auto
auto
auto
auto

=
=
=
=
=

0,
0,
0,
0,
0,

stati
stati
stati
stati
stati

=
=
=
=
=

0
1
2
3
4

Como se puede observar la variable a_var es reada ada vez que se llama a la fun ion. La variable s_var es
reada en la primera llamada y despues re uerda su valor, es de ir, no se destruye uando termina la fun ion.

7.6. Ejer i ios


1. Es ribir un programa que use el tipo enumerate para mostrar el nombre de un mes, su prede esor y su su esor.
El mes se ingresara desde el te lado dando un numero entre 1 y 12.
2. Es ribir un programa que ontenga una fun ion que pueda re ibir dos estru turas que ontienen las oordenadas
en el plano de dos puntos dados, de los uales se desea ono er su punto medio.

Cap
tulo 8

Apuntadores
Los apuntadores son una parte fundamental de C. Si usted no puede usar los apuntadores apropiadamente enton es
esta perdiendo la poten ia y la exibilidad que C ofre e basi amente. El se reto para C esta en el uso de apuntadores.
C usa los apuntadores en forma extensiva. >Porque?
Es la uni a forma de expresar algunos al ulos.
Se genera odigo ompa to y e iente.
Es una herramienta muy poderosa.
C usa apuntadores expl itamente on:
Es la uni a forma de expresar algunos al ulos.
Se genera odigo ompa to y e iente.
Es una herramienta muy poderosa.
C usa apuntadores expl itamente on:
Arreglos,
Estru turas y
Fun iones

8.1. De ni ion de un apuntador


Un apuntador es una variable que ontiene la dire ion en memoria de otra variable. Se pueden tener apuntadores
a ualquier tipo de variable.
El operador unario o mon
adi o & devuelve la dire ion de memoria de una variable.
El operador de indire i
on o dereferen ia * devuelve el \ ontenido de un objeto apuntado por un apuntador".
Para de larar un apuntador para una variable entera ha er:
int *apuntador;

Se debe aso iar a ada apuntador un tipo parti ular. Por ejemplo, no se puede asignar la dire ion de un short int
a un long int.
Para tener una mejor idea, onsiderar el siguiente odigo:
46

CAPITULO 8. APUNTADORES

47

main()
{
int x = 1, y = 2;
int *ap;
ap = &x;
y = *ap;
x = ap;
*ap = 3;
}

Cuando se ompile el odigo se mostrara el siguiente mensaje:

warning: assignment makes integer from pointer without a ast.

Con el objetivo de entender el omportamiento del odigo supongamos que la variable x esta en la lo alidad de
la memoria 100, y en 200 y ap en 1000. Nota: un apuntador es una variable, por lo tanto, sus valores ne esitan ser
guardados en algun lado.
int x = 1, y = 2;
int *ap;
ap = &x;

100
1

200
2

ap

1000
100

Las variables x e y son de laradas e ini ializadas on 1 y 2 respe tivamente, ap es de larado omo un apuntador
a entero y se le asigna la dire ion de x (&x). Por lo que ap se arga on el valor 100.
y = *ap;

100
x 1

200
y 1

1000
ap 100

Despues y obtiene el ontenido de ap. En el ejemplo ap apunta a la lo alidad de memoria 100 | la lo alidad de
x. Por lo tanto, y obtiene el valor de x | el ual es 1.
x = ap;

100
x 100

200
y 1

1000
ap 100

Como se ha visto C no es muy estri to en la asigna ion de valores de diferente tipo (apuntador a entero). As que
es perfe tamente legal (aunque el ompilador genera un aviso de uidado) asigna el valor a tual de ap a la variable
x. El valor de ap en ese momento es 100.

CAPITULO 8. APUNTADORES

48

*ap = 3;

100
3

200
1

ap

1000
100

Finalmente se asigna un valor al ontenido de un apuntador (*ap).

Importante: Cuando un apuntador es de larado apunta a algun lado. Se debe ini ializar el apuntador antes de

usarlo. Por lo que:

main()
{
int *ap;
*ap = 100;
}

puede generar un error en tiempo de eje u ion o presentar un omportamiento errati o.


El uso orre to sera:
main()
{
int *ap;
int x;
ap = &x;
*ap = 100;
}

Con los apuntadores se puede realizar tambien aritmeti a entera, por ejemplo:
main()
{
float *flp, *flq;
*flp = *flp + 10;
++*flp;
(*flp)++;
flq = flp;
}

NOTA: Un apuntador a ualquier tipo de variables es una dire ion en memoria | la ual es una dire ion entera,
pero un apuntador NO es un entero.
La razon por la ual se aso ia un apuntador a un tipo de dato, es por que se debe ono er en uantos bytes esta
guardado el dato. De tal forma, que uando se in rementa un apuntador, se in rementa el apuntador por un \bloque"
de memoria, en donde el bloque esta en fun ion del tama~no del dato.
Por lo tanto para un apuntador a un har, se agrega un byte a la dire ion y para un apuntador a entero o a
otante se agregan 4 bytes. De esta forma si a un apuntador a otante se le suman 2, el apuntador enton es se mueve
dos posi iones oat que equivalen a 8 bytes.

CAPITULO 8. APUNTADORES

49

8.2. Apuntadores y Fun iones


Cuando C pasa argumentos a fun iones, los pasa por valor, es de ir, si el parametro es modi ado dentro de la
fun ion, una vez que termina la fun ion el valor pasado de la variable permane e inalterado.
Hay mu hos asos que se quiere alterar el argumento pasado a la fun ion y re ibir el nuevo valor una vez que la
fun ion ha terminado. Para ha er lo anterior se debe usar una llamada por referen ia, en C se puede simular pasando
un puntero al argumento. Con esto se provo a que la omputadora pase la dire ion del argumento a la fun ion.
Para entender mejor lo anterior onsideremos la fun ion swap() que inter ambia el valor de dos argumentos
enteros:
void swap(int *px, int *py);
main()
{
int x, y;
x = 10;
y = 20;
printf("x=%d\ty=%d\n",x,y);
swap(&x, &y);
printf("x=%d\ty=%d\n",x,y);
}
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;

/* guarda el valor de la dire ion x */


/* pone y en x */
/* pone x en y */

8.3. Apuntadores y arreglos


Existe una rela ion estre ha entre los punteros y los arreglos. En C, un nombre de un arreglo es un ndi e a
la dire ion de omienzo del arreglo. En esen ia, el nombre de un arreglo es un puntero al arreglo. Considerar lo
siguiente:
int a[10, x;
int *ap;
ap = &a[0;

/* ap apunta a la dire ion de a[0 */

x = *ap;

/* A x se le asigna el ontenido de ap (a[0 en este aso) */

*(ap + 1) = 100; /* Se asigna al segundo elemento de 'a' el valor 100 usando ap*/

Como se puede observar en el ejemplo la senten ia a[t es identi a a ap+t. Se debe tener uidado ya que C no
ha e una revision de los lmites del arreglo, por lo que se puede ir fa ilmente mas alla del arreglo en memoria y
sobrees ribir otras osas.

CAPITULO 8. APUNTADORES

50

C sin embargo es mu ho mas sutil en su rela ion entre arreglos y apuntadores. Por ejemplo se puede te lear
solamente:
ap = a; en vez de ap = &a[0; y tambien *(a + i) en vez de a[i, esto es, &a[i es equivalente on
a+i.

Y omo se ve en el ejemplo, el dire ionamiento de apuntadores se puede expresar omo:


a[i que es equivalente a *(ap + i)

Sin embargo los apuntadores y los arreglos son diferentes:


Un apuntador es una variable. Se puede ha er ap = a y ap++.
Un arreglo NO ES una variable. Ha er a = ap y a++ ES ILEGAL.
Este parte es muy importante, asegurese haberla entendido.
Con lo omentado se puede entender omo los arreglos son pasados a las fun iones. Cuando un arreglo es pasado
a una fun ion lo que en realidad se le esta pasando es la lo alidad de su elemento ini ial en memoria.
Por lo tanto:
strlen(s) es equivalente a strlen(&s[0)

Esta es la razon por la ual se de lara la fun ion omo:


int strlen( har s[); y una de lara ion equivalente es int strlen( har *s);

ya que har s[ es igual que har *s.


La fun ion strlen() es una fun ion de la bibliote a estandar que regresa la longitud de una adena. Se muestra
enseguida la version de esta fun ion que podra es ribirse:
int strlen( har *s)
{
har *p = s;
while ( *p != '\0' )
p++;
return p - s;
}

Se muestra enseguida una fun ion para opiar una adena en otra. Al igual que en el ejer i io anterior existe en
la bibliote a estandar una fun ion que ha e lo mismo.
void str py( har *s, har *t)
{
while ( (*s++ = *t++) != '\0' );
}

En los dos ultimos ejemplos se emplean apuntadores y asigna ion por valor. Nota: Se emplea el uso del ara ter
nulo on la senten ia while para en ontrar el n de la adena.

CAPITULO 8. APUNTADORES

51

8.4. Arreglos de apuntadores


En C se pueden tener arreglos de apuntadores ya que los apuntadores son variables.
A ontinua ion se muestra un ejemplo de su uso: ordenar las lneas de un texto de diferente longitud.
Los arreglos de apuntadores son una representa ion de datos que manejan de una forma e iente y onveniente
lneas de texto de longitud variable.
>Como se puede ha er lo anterior?
1. Guardar todas las lneas en un arreglo de tipo har grande. Observando que \n mar a el n de ada
lnea. Ver gura 8.1.
2. Guardar los apuntadores en un arreglo diferente donde ada apuntador apunta al primer ara ter
de ada lnea.
3. Comparar dos lneas usando la fun ion de la bibliote a estandar str mp().
4. Si dos lneas estan desa omodadas | inter ambiar (swap) los apuntadores (no el texto).
ABC ..... \nDEF .... \n CAT .... \n ....
p[0]

p[1]

p[2]

ABC

ABC

DEF

DEF

CAT

CAT

Figura 8.1: Arreglos de apuntadores (Ejemplo de ordenamiento de adenas).


Con lo anterior se elimina:
el manejo ompli ado del alma enamiento.
alta sobre arga por el movimiento de lneas.

8.5. Arreglos multidimensionales y apuntadores


Un arreglo multidimensional puede ser visto en varias formas en C, por ejemplo:
Un arreglo de dos dimensiones es un arreglo de una dimension, donde ada uno de los elementos es en s mismo
un arreglo.
Por lo tanto, la nota ion
a[n[m

nos indi a que los elementos del arreglo estan guardados renglon por renglon.
Cuando se pasa una arreglo bidimensional a una fun ion se debe espe i ar el numero de olumnas | el numero
de renglones es irrelevante.
La razon de lo anterior, es nuevamente los apuntadores. C requiere ono er uantas son las olumnas para que
pueda brin ar de renglon en renglon en la memoria.
Considerando que una fun ion deba re ibir int a[5[35, se puede de larar el argumento de la fun ion omo:

CAPITULO 8. APUNTADORES

52

f( int a[[35 ) { ..... }

o aun
f( int (*a)[35 ) { ..... }

En el ultimo ejemplo se requieren los parenteis (*a) ya que [ tiene una pre eden ia mas alta que *.
Por lo tanto:
int (*a)[35; de lara un apuntador a un arreglo de 35 enteros, y por ejemplo si ha emos la siguiente
referen ia a+2, nos estaremos re riendo a la dire ion del primer elemento que se en uentran en el ter er
renglon de la matriz supuesta, mientras que
int *a[35; de lara un arreglo de 35 apuntadores a enteros.

Ahora veamos la diferen ia (sutil) entre apuntadores y arreglos. El manejo de adenas es una apli a ion omun
de esto.
Considera:
har *nomb[10;
har anomb[10[20;

En donde es valido ha er nomb[3[4 y anomb[3[4 en C.


Sin embargo:
- anomb es un arreglo verdadero de 200 elementos de dos dimensiones tipo har.
- El a eso de los elementos anomb en memoria se ha e bajo la siguiente formula 20*renglon + olumna
+ dire ion base
- En ambio nomb tiene 10 apuntadores a elementos.

NOTA: si ada apuntador en nomb indi a un arreglo de 20 elementos enton es y solamente enton es 200 hars
estaran disponibles (10 elementos).
Con el primer tipo de de lara ion se tiene la ventaja de que ada apuntador puede apuntar a arreglos de diferente
longitud.
Considerar:
har *nomb[ = { "No mes", "Ene", "Feb", "Mar", .... };
har anomb[[15 = { "No mes", "Ene", "Feb", "Mar", ... };

Lo ual gra amente se muestra en la gura 8.2. Se puede indi ar que se ha e un manejo mas e iente del espa io
ha iendo uso de un arreglo de apuntadores y usando un arreglo bidimensional.

CAPITULO 8. APUNTADORES

53
anomb

15 elementos

No mes\0
Ene\0
Feb\0
Mar\0

13

nomb
0

No mes\0

Ene\0

Feb\0

Figura 8.2: Arreglo de 2 dimensiones VS. arreglo de apuntadores.

8.6. Ini ializa ion estati a de arreglos de apuntadores


La ini ializa ion de arreglos de apuntadores es una apli a ion ideal para un arreglo estati o interno, por ejemplo:
fun _ ualquiera()
{
stati har *nomb[ = { "No mes", "Ene", "Feb", "Mar", .... };
}

Re ordando que on el espe i ador de alma enamiento de lase stati se reserva en forma permanente memoria
el arreglo, mientras el odigo se esta eje utando.

8.7. Apuntadores y estru turas


Los apuntadores a estru turas se de nen fa ilmente y en una forma dire ta. Considerar lo siguiente:
main()
{
stru t COORD { float x,y,z; } punto;
stru t COORD *ap_punto;
punto.x = punto.y = punto.z = 1;
ap_punto = &punto; /* Se asigna punto al apuntador */
ap_punto->x++;
ap_punto->y+=2;
ap_punto->z=3;

/* Con el operador -> se a esan los miembros */


/*
de la estru tura apuntados por ap_punto */

CAPITULO 8. APUNTADORES

54

Otro ejemplo son las listas ligadas:


typedef stru t {
int valor;
stru t ELEMENTO *sig;
} ELEMENTO;
ELEMENTO n1, n2;
n1.sig = &n2;

La asigna ion que se ha e orresponde a la gura 8.3


valor

*sig

n1

valor

*sig

n2

Figura 8.3: Esquema de una lista ligada on 2 elementos.

Nota: Solamente se puede de larar sig omo un apuntador tipo ELEMENTO. No se puede tener un elemento del

tipo variable ya que esto generara una de ni ion re ursiva la ual no esta permitida. Se permite poner una referen ia
a un apuntador ya que los los bytes se dejan de lado para ualquier apuntador.

8.8. Fallas omunes on apuntadores


A ontinua ion se muestran dos errores omunes que se ha en on los apuntadores.

No asignar un apuntador a una dire ion de memoria antes de usarlo


int *x
*x = 100;

lo ade uado sera, tener primeramente una lo alidad fsi a de memoria, digamos int y;
int *x, y;
x = &y;
*x = 100;

Indire ion no valida


Supongamos que se tiene una fun ion llamada mallo () la ual trata de asignar memoria dinami amente (en
tiempo de eje u ion), la ual regresa un apuntador al bloque de memoria requerida si se pudo o un apuntador
a nulo en otro aso.
har *mallo () | una fun ion de la bibliote a estandar que se vera mas adelante.

Supongamos que se tiene un apuntador har *p


Considerar:

CAPITULO 8. APUNTADORES

*p = ( har *) mallo (100):

55
/* pide 100 bytes de la memoria */

*p = 'y';

Existe un error en el odigo anterior. >Cual es?


El * en la primera lnea ya que mallo regresa un apuntador y *p no apunta a ninguna dire ion.
El odigo orre to debera ser:
p = ( har *) mallo (100);

Ahora si mallo no puede regresar un bloque de memoria, enton es p es nulo, y por lo tanto no se podra ha er:
*p = 'y';

Un buen programa en C debe revisar lo anterior, por lo que el odigo anterior puede ser rees rito omo:
p = ( har *) mallo (100):

/* pide 100 bytes de la memoria */

if ( p == NULL )
{
printf("Error: fuera de memoria\n");
exit(1);
}
*p = 'y';

8.9. Ejer i ios


1. Es ribir el programa que ordena las lneas de un texto ledo desde la entrada estandar, donde ada lnea tiene
diferente longitud, segun lo des rito en la se ion de arreglo de apuntadores.
2. Es ribir una fun ion que onvierta una adena s a un numero de punto otante usando apuntadores. Considerar
que el numero tiene el siguiente formato 99999999.999999, es de ir, no se dara en nota ion ient a. La fun ion
debera suministrarsele una adena y debera devolver un numero.
3. Es ribir un programa que en uentre el numero de ve es que una palabra dada (esto es, una adena orta)
o urre en una senten ia (una adena larga).
Leer los datos de la entrada estandar. La primera lnea es una sola palabra, en la segunda lnea se tiene un texto
general. Leer ambas hasta en ontrar un ara ter de nueva lnea. Re ordar que se debe insertar un ara ter nulo
antes de pro esar.
La salida tpi a podra ser:
La palabra es "el"
La senten ia es "el perro, el gato y el anario"
La palabra o urrio 3 ve es.

Cap
tulo 9

Asigna i
on dinami a de memoria y
Estru turas dinami as
La asigna ion dinami a de memoria es una ara tersti a de C. Le permite al usuario rear tipos de datos y
estru turas de ualquier tama~no de a uerdo a las ne esidades que se tengan en el programa.
Se revisaran dos de las apli a iones mas omunes:
Arreglos dinami os
Estru turas dinami as de datos.

9.1. Uso de mallo , sizeof y free


La fun ion mallo es empleada omunmente para intentar \tomar" una por ion ontigua de memoria. Esta
de nida omo:
void *mallo (size_t size);

Lo anterior indi a que regresara un apuntador del tipo void *, el ual es el ini io en memoria de la por ion
reservada de tama~no size. Si no puede reservar esa antidad de memoria la fun ion regresa un apuntador nulo o
NULL

Dado que void * es regresado, C asume que el apuntador puede ser onvertido a ualquier tipo. El tipo de
argumento size_t esta de nido en la abe era stddef.h y es un tipo entero sin signo.
Por lo tanto:
har * p;
p = ( har *) mallo (100);

intenta obtener 100 bytes y asignarlos a la dire ion de ini io a p.


Es usual usar la fun ion sizeof() para indi ar el numero de bytes, por ejemplo:
int *ip;
ip = (int *) mallo (100 * sizeof(int) );

El ompilador de C requiere ha er una onversion del tipo. La forma de lograr la oer ion ( ast) es usando

( har *) y (int *), que permite onvertir un apuntador void a un apuntador tipo har e int respe tivamente.

56

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

57

Ha er la onversion al tipo de apuntador orre to asegura que la aritmeti a on el apuntador fun ionara de forma
orre ta.
Es una buena pra ti a usar sizeof() aun si se ono e el tama~no a tual del dato que se requiere, | ya que de
esta forma el odigo se ha e independiente del dispositivo (portabilidad).
La fun ion sizeof() puede ser usada para en ontrar el tama~no de ualquier tipo de dato, variable o estru tura.
Simplemente se debe propor ionar uno de los anteriores omo argumento a la fun ion.
Por lo tanto:
int i;
stru t COORD {float x,y,z};
stru t COORD *pt;
sizeof(int), sizeof(i), sizeof(stru t COORD) y
sizeof(PT) son tambien senten ias orre tas.

En el siguiente ejemplo se reserva memoria para la variable ip, en donde se emplea la rela ion que existe entre
apuntadores y arreglos, para manejar la memoria reservada omo un arreglo. Por ejemplo, se pueden ha er osas
omo:
main()
{
int *ip, i;
ip = (int *) mallo (100 * sizeof(int) );
ip[0 = 1000;
for (i=0; i<100; ++i)
s anf("%d",ip++);
}

Cuando se ha terminado de usar una por ion de memoria siempre se debera liberar usando la fun ion free().
Esta fun ion permite que la memoria liberada este disponible nuevemente quizas para otra llamada de la fun ion
mallo ()

La fun ion free() toma un apuntador omo un argumento y libera la memoria a la ual el apuntador ha e
referen ia.

9.2. allo y reallo


Existen dos fun iones adi ionales para reservar memoria, allo () y reallo (). Los prototipos son dados a
ontinua ion:
void * allo (size_t nmemb, size_t size);
void *reallo (void *ptr, size_t size);

Cuando se usa la fun ion mallo () la memoria no es ini ializada (a ero ) o borrada. Si se quiere ini ializar la
memoria enton es se puede usar la fun ion allo . La fun ion allo es omputa ionalmente un po o mas ara
pero, o asionalmente, mas onveniente que mallo . Se debe observar tambien la diferen ia de sintaxis entre allo

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

58

y mallo , ya que allo toma el numero de elementos deseados (nmemb) y el tama~no del elemento (size), omo dos
argumentos individuales.
Por lo tanto para asignar a 100 elementos enteros que esten ini ializados a ero se puede ha er:
int *ip;
ip = (int *) allo (100, sizeof(int) );

La fun ion reallo intenta ambiar el tama~no de un bloque de memoria previamente asignado. El nuevo tama~no
puede ser mas grande o mas peque~no. Si el bloque se ha e mas grande, enton es el ontenido anterior permane e
sin ambios y la memoria es agregada al nal del bloque. Si el tama~no se ha e mas peque~no enton es el ontenido
sobrante permane e sin ambios.
Si el tama~no del bloque original no puede ser redimensionado, enton es reallo intentara asignar un nuevo
bloque de memoria y opiara el ontenido anterior. Por lo tanto, la fun ion devolvera un nuevo apuntador (o de
valor diferente al anterior), este nuevo valor sera el que debera usarse. Si no puede ser reasignada nueva memoria la
fun ion reallo devuelve NULL.
Si para el ejemplo anterior, se quiere reasignar la memoria a 50 enteros en vez de 100 apuntados por ip, se hara;
ip = (int *) reallo ( ip, 50*sizeof(int) );

9.3. Listas ligadas


Regresando al ejemplo del aptulo anterior se de nio la estru tura:
typedef stru t {
int valor;
stru t ELEMENTO *sig;
} ELEMENTO;

La ual puede re er en forma dinami a.


ELEMENTO *liga;
liga = (ELEMENTO *) mallo ( sizeof(ELEMENT) ); /* Asigna memoria para liga */
free(liga);

/* libera la memoria asignada al apuntador liga usando free() */

9.4. Programa de revision


La ola es una ole ion de ordenada de elementos de la que se pueden borrar elementos en un extremo (llamado
el frente de la ola) o insertarlos en el otro (llamado el nal de la ola.
Se muestra a ontinua ion el odigo ompleto para manipular esta estru tura:
/* ola.
/* Demo de estru turas dinami as en C
#in lude <stdio.h>
#define FALSO 0

*/
*/

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

typedef stru t nodo {


int
dato;
stru t nodo *liga;
} elemento_lista;
void Menu (int *op ion);
elemento_lista * AgregaDato (elemento_lista * apuntlista, int dato);
elemento_lista * BorrarDato (elemento_lista * apuntlista);
void ImprCola (elemento_lista * apuntlista);
void LimpCola (elemento_lista * apuntlista);
main ()
{
elemento_lista listmember, *apuntlista;
int
dato, op ion;
apuntlista = NULL;
do {
Menu (&op ion);
swit h (op ion) {
ase 1:
printf ("Ingresa un dato que sera agregado ");
s anf ("%d", &dato);
apuntlista = AgregaDato (apuntlista, dato);
break;
ase 2:
if (apuntlista == NULL)
printf ("<Cola va ia!\n");
else
apuntlista = BorrarDato (apuntlista);
break;
ase 3:
ImprCola (apuntlista);
break;
ase 4:
break;
default:
printf ("Op ion no valida - intentar nuevamente\n");
break;
}
} while (op ion != 4);
LimpCola (apuntlista);
}

/* fin de main */

59

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

60

void Menu (int *op ion)


{
har

lo al;

printf("\nEntre\t1 para agregar un dato,\n\t2 para borrar un dato,\n\t3 para mostrar el ont
do {
lo al = get har ();
if ((isdigit (lo al) == FALSO) && (lo al != '\n'))
{
printf ("\nSe debe ingresar un entero.\n");
printf ("Te lee 1 para agregar, 2 para borrar, 3 para imprimir, 4 para salir\n");
}
} while (isdigit ((unsigned har) lo al) == FALSO);
*op ion = (int) lo al - '0';
}

elemento_lista *AgregaDato (elemento_lista *apuntlista, int dato)


{
elemento_lista * lp = apuntlista;
if (apuntlista != NULL) {
while (apuntlista -> liga != NULL)
apuntlista = apuntlista -> liga;
apuntlista -> liga = (stru t nodo *) mallo (sizeof (elemento_lista));
apuntlista = apuntlista -> liga;
apuntlista -> liga = NULL;
apuntlista -> dato = dato;
return lp;
}
else
{
apuntlista = (stru t nodo *) mallo (sizeof (elemento_lista));
apuntlista -> liga = NULL;
apuntlista -> dato = dato;
return apuntlista;
}
}
elemento_lista *BorrarDato (elemento_lista *apuntlista)
{
elemento_lista *tempp;
printf ("El elemento borrado es %d\n", apuntlista -> dato);
tempp = apuntlista -> liga;
free (apuntlista);

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

61

return tempp;
}

void ImprCola (elemento_lista *apuntlista)


{
if (apuntlista == NULL)
printf ("La ola esta va ia !!\n");
else
while (apuntlista != NULL) {
printf ("%d\t", apuntlista -> dato);
apuntlista = apuntlista -> liga;
}
printf ("\n");
}

void LimpCola (elemento_lista *apuntlista)


{
while (apuntlista != NULL) {
apuntlista = BorrarDato (apuntlista);
}
}

9.5. Ejer i ios


1. Es ribir un programa que lea un numero, que indi a uantos numeros enteros seran guardados en un arreglo,
rear el arreglo para alma enar el tama~no exa to de los datos y enton es leer los enteros que seran guardados
en el arreglo.
2. Es ribir un programa para ordenar una se uen ia de numeros usando un arbol binario. Un arbol binario es
una estru tura tipo arbol on solamente 2 (posibles) ramas de ada nodo. Cada rama enton es representa una
de ision de falso o verdadero. Para ordenar los numeros simplemente asignar a la rama izquierda los numeros
menores respe to al numero del nodo, y en la rama dere ha el resto (es de ir, los que son mayores o iguales a).
Por lo tanto, si la lista de entrada es: 14 15 4 9 7 18 3 5 16 4 20 17 0 14 5, se debe generar el arbol de
la gura 9.1.
Para obtener una lista ordenada en forma as endente, re orrer el arbol en preorden (depth- rst order ), es de ir,
visitar la raz, re orrer el subarbol izquierdo en orden y re orrer el subarbol dere ho en orden. Por lo que la
salida debera ser:
Los valores ordenados son:
0 3 4 4 5 5 7 9 14 14 15 16 17 18 20

Mostrar 10 valores por lnea.

 DINAMICA


CAPITULO 9. ASIGNACION
DE MEMORIA Y ESTRUCTURAS DINAMICAS

14
4

15

18

14

16

17

20

Figura 9.1: Arbol binario.

62

Cap
tulo 10

Topi os avanzados on apuntadores


Se han revisado varias apli a iones y te ni as que usan apuntadores en los aptulos anteriores. As mismo se han
introdu ido algunos temas avanzados en el uso de apuntadores. En este aptulo se profundizan algunos topi os que
ya han sido men ionados brevemente y otros que ompletan la revision de apuntadores en C.
En este aptulo se desarrolla lo siguiente:
Se examinan apuntadores a apuntadores on mas detalle.
Como se usan los apuntadores en la lnea de entrada.
Y se revisan los apuntadores a fun iones.

10.1. Apuntadores a apuntadores


Un arreglo de apuntadores es lo mismo que apuntadores a apuntadores. El on epto de arreglos de apuntadores
es dire to ya que el arreglo mantiene su signi ado laro. Sin embargo, se pueden onfundir los apuntadores a
apuntadores.
Un apuntador a un apuntador es una forma de dire ionamiento indire to multiple, o una adena de apuntadores.
Como se ve en la gura 10.1, en el aso de un apuntador normal, el valor del apuntador es la dire ion de la variable
que ontiene el valor deseado. En el aso de un apuntador a un apuntador, el primer apuntador ontiene la dire ion
del segundo apuntador, que apunta a la variable que ontiene el valor deseado.
Se puede llevar dire ionamiento indire to multiple a ualquier extension deseada, pero hay po os asos donde
mas de un apuntador a un apuntador sea ne esario, o in luso bueno de usar. La dire ion indire ta en ex eso es
dif il de seguir y propensa a errores on eptuales.
Se puede tener un apuntador a otro apuntador de ualquier tipo. Considere el siguiente odigo:
main()
{
har h;
/* Un ara ter */
har *p h; /* Un apuntador a ara ter */
har **pp h; /* Un apuntador a un apuntador a ara ter */
h = 'A';
p h = & h;
pp h = &p h;
printf("% \n", **pp h);

/* muestra el valor de h */

63


CAPITULO 10. TOPICOS
AVANZADOS CON APUNTADORES

64

Lo anterior se puede visualizar omo se muestra en la gura 10.1, en donde se observa que **pp h se re ere
a la dire ion de memoria de *p h, la ual a su vez se re ere a la dire ion de memoria de la variable h. Pero
>que signi a lo anterior en la pra ti a?

ppch

pch

ch

Figura 10.1: Apuntador a un apuntador, y apuntador a un har .


Se debe re ordar que har * se re ere a una adena la ual termina on un nulo. Por lo tanto, un uso omun y
onveniente es de larar un apuntador a un apuntador, y el apuntador a una adena, ver gura 10.2.
String
ppch

pch

Figura 10.2: Apuntador a un apuntador, y apuntador a una adena.


Tomando un paso mas alla lo anterior, se pueden tener varias adenas apuntadas por el apuntador, ver gura
10.3
String 0
ppch

String 1
String 3
String 4
String 5
String 6
pch

Figura 10.3: Apuntador a varias adenas.


Se pueden ha er referen ias a adenas individuales mediante pp h[0, pp h[1, .... Esto es identi o a haber
de larado har *pp h[.
Una apli a ion omun de lo anterior es en los argumentos de la lnea de omandos que se revisaran a ontinua ion.

10.2. Entrada en la lnea de omandos


C permite leer argumentos en la lnea de omandos, los uales pueden ser usados en los programas.
Los argumentos son dados o te leados despues del nombre del programa al momento de ser eje utado el programa.
Lo anterior se ha visto al momento de ompilar, por ejemplo:
g -o prog prog.

donde g es el ompilador y -o prog prog. son los argumentos.


Para poder usar los argumentos en el odigo se debe de nir omo sigue la fun ion main.


CAPITULO 10. TOPICOS
AVANZADOS CON APUNTADORES

65

main(int arg , har **argv)

o
main(int arg , har *argv[)

Con lo que la fun ion prin ipal tiene ahora sus propios argumentos. Estos son solamente los uni os argumentos
que la fun ion main a epta.
* arg es el numero de argumentos dados | in luyendo el nombre del programa.
* argv es un arreglo de adenas que tiene a ada uno de los argumentos de la lnea de omandos | in luyendo
el nombre del programa en el primer elemento del arreglo.
Se muestra a ontinua ion un programa de ejemplo:
main (int arg , har **argv)
{
/* Este programa muestra los argumentos de la linea de omandos */
int i;
printf("arg = %d\n\n",arg );
for (i=0; i<arg ; ++i)
printf("\t\targv[%d: %s\n", i, argv[i);
}

Suponiendo que se ompila y se eje uta on los siguientes argumentos:


args f1 "f2 y f3" f4 5 FIN

La salida sera:
arg = 6
argv[0:
argv[1:
argv[2:
argv[3:
argv[4:
argv[5:

args
f1
f2 y f3
f4
5
FIN

Observar lo siguiente:
- argv[0 ontiene el nombre del programa.
- arg uenta el numero de argumentos in luyendo el nombre del programa.
- Los espa ios en blan o delimitan el n de los argumentos.
- Las omillas dobles " " son ignoradas y son usadas para in luir espa ios dentro de un argumento.


CAPITULO 10. TOPICOS
AVANZADOS CON APUNTADORES

66

10.3. Apuntadores a fun iones


Los apuntadores a fun iones son quiza uno de los usos mas onfusos de los apuntadores en C. Los apuntadores a
fun iones no son tan omunes omo otros usos que tienen los apuntadores. Sin embargo, un uso omun es uando se
pasan apuntadores a fun iones omo parametros en la llamada a una fun ion.
Lo anterior es espe ialmente util uando se deben usar distintas fun iones quizas para realizar tareas similares
on los datos. Por ejemplo, se pueden pasar los datos y la fun ion que sera usada por alguna fun ion de ontrol. Como
se vera mas adelante la bibliote a estandar de C da fun iones para ordenamiento (qsort ) y para realizar busqueda
(bsear h ), a las uales se les pueden pasar fun iones.
Para de larar un apuntador a una fun ion se debe ha er:
int (*pf) ();

Lo ual de lara un apuntador pf a una fun ion que regresa un tipo de dato int. Todava no se ha indi ado a que
fun ion apunta.
Suponiendo que se tiene una fun ion int f(), enton es simplemente se debe es ribir:
pf = &f;

para que pf apunte a la fun ion f ().


Para que trabaje en forma ompleta el ompilador es onveniente que se tengan los prototipos ompletos de las
fun iones y los apuntadores a las fun iones, por ejemplo:
int f(int);
int (*pf) (int) = &f;

Ahora f() regresa un entero y toma un entero omo parametro.


Se pueden ha er osas omo:
ans = f(5);
ans = pf(5);

los uales son equivalentes.


La fun ion de la bibliote a estandar qsort es muy util y esta dise~nada para ordenar un arreglo usando un valor
omo llave de ualquier tipo para ordenar en forma as endente.
El prototipo de la fun ion qsort de la bibliote a stdlib.h es:
void qsort(void *base, size_t nmiemb, size_t tam,
int (* ompar)( onst void *, onst void *));

El argumento base apunta al omienzo del ve tor que sera ordenado, nmiemb indi a el tama~no del arreglo, tam
es el tama~no en bytes de ada elemento del arreglo y el argumento nal ompar es un apuntador a una fun ion.
La fun ion qsort llama a la fun ion ompar la ual es de nida por el usuario para omparar los datos uando
se ordenen. Observar que qsort onserva su independen ia respe to al tipo de dato al dejarle la responsabilidad al
usuario. La fun ion ompar debe regresar un determinado valor entero de a uerdo al resultado de ompara ion, que
debe ser:

menor que ero : si el primer valor es menor que el segundo.


ero : si el primer valor es igual que el segundo.
mayor que ero : si el primer valor es mayor que el segundo.


CAPITULO 10. TOPICOS
AVANZADOS CON APUNTADORES

67

A ontinua ion se muestra un ejemplo que ordena un arreglo de ara teres, observar que en la fun ion omp, se
ha e un ast para forzar el tipo void * al tipo har *.
#in lude <stdlib.h>
int omp( onst void *i, onst void *j);
main()
{
int i;
har ad[ = "fa ultad de ien ias fisi o-matemati as";
printf("\n\nArreglo original: \n");
for (i=0; i<strlen( ad); i++)
printf("% ", ad[i);
qsort( ad, strlen( ad), sizeof( har), omp );
printf("\n\nArreglo ordenado: \n");
for (i=0; i<strlen( ad); i++)
printf("% ", ad[i);
printf("\n");
}
int omp( onst void *i, onst void *j)
{
har *a, *b;
a = ( har *) i; /* Para forzar void * al tipo har *, se ha e ast */
b = ( har *) j; /*
empleando ( har *)
*/
return *a - *b;
}

10.4. Ejer i ios


1. Es ribir un programa que muestre las ultimas lneas de un texto de entrada. Por defe to o \default" n debera ser
7, pero el programa debera permitir un argumento op ional tal que
ultlin n

muestra las ultimas n lneas, donde n es un entero. El programa debera ha er el mejor uso del espa io de
alma enamiento. (El texto de entrada podra ser ledo de un ar hivo dado desde la lnea de omandos o leyendo
un ar hivo de la entrada estandar.)
2. Es ribir un programa que ordene una lista de enteros en forma as endente. Sin embargo, si una op ion r esta
presente en la lnea de omandos el programa debera ordenar la lista en forma des endente.
3. Es ribir un programa que lea la siguiente estru tura y ordene los datos por la llave usando qsort


CAPITULO 10. TOPICOS
AVANZADOS CON APUNTADORES

typedef stru t {
har llave[10;
int algo_mas;
} Re ord;

68

Cap
tulo 11

Operadores de bajo nivel y ampos de bit


Se ha visto omo los apuntadores nos dan ontrol sobre las opera iones de bajo nivel de la memoria.
Mu hos programas (por ejemplo, apli a iones del tipo sistemas) operan a tualmente a bajo nivel donde bits
individuales deben ser manipulados.
La ombina ion de apuntadores y operadores a nivel bit ha en de C util para mu has apli a iones de bajo nivel
y pueden asi reemplazar al odigo ensamblador. (Solamente un 10 % aproximadamente de UNIX esta en odigo
ensamblador el resto es C.)

11.1. Operadores sobre bits


Los operadores sobre bits de C se resumen en la siguiente tabla:
Operador
&
|
^
~
<<
>>

A ion
Y
O
O ex lusiva (XOR)
Complemento a uno
Nega ion
Desplazamiento a la izquierda
Desplazamiento a la dere ha

No se debe onfundir el operador & on el operador &&: & es el operador Y sobre bits, && es el operador logi o Y.
Similarmente los operadores | y ||.
El operador unario ~ solo requiere un argumento a la dere ha del operador.
Los operadores de desplazamiento, >> y <<, mueven todos los bits en una posi ion ha ia la dere ha o la izquierda
un determinado numero de posi iones. El formato general de la senten ia de desplazamiento a la dere ha es:
variable >> num_pos_de_bit

y el formato general de desplazamiento a la izquierda es


variable << num_pos_de_bit

Como los operadores desplazan bits en un sentido, la omputadora trae eros en el otro extremo. Se debe re ordar
que un desplazamiento no es una rota ion: los bits desplazados en un extremo no vuelven al otro. Se pierden y los
eros trados los reemplazan.
Una apli a ion que tienen los operadores de desplazamiento de bits es para realizar multipli a iones y divisiones
rapidas on enteros. Como se ve en la siguiente tabla, donde un desplazamiento a la izquierda es multipli ar por 2 y
uno a la dere ha dividir por 2.
69

CAPITULO 11. OPERADORES DE BAJO NIVEL Y CAMPOS DE BIT

har x
x
x
x
x
x
x

= 7;
<< 1;
<< 3;
<< 2;
>> 1;
>> 2;

Eje u ion
0
0
0
1
0
0

0
0
1
1
1
0

0
0
1
0
1
0

0
0
1
0
0
1

0
1
0
0
0
1

1
1
0
0
0
0

1
1
0
0
0
0

1
0
0
0
0
0

70

Valor de x
7
14
112
192
96
24

Los desplazamientos son mu ho mas rapidos que la multipli a ion a tual (*) o la division (/) por dos. Por lo
tanto, si se quieren multipli a iones o divisiones rapidas por 2 use desplazamientos.
Con la nalidad de ilustrar algunos puntos de los operadores sobre bits, se muestra la siguiente fun ion ontbit,
la ual uenta los bits puestos a 1 en un numero de 8 bits (unsigned har) pasado omo un argumento a la fun ion.
int ontbit(unsigned har x)
{
int ount;
for ( ount=0; x!=0; x>>=1)
if ( x & 1)
ount++;
return ount;
}

En esta fun ion se ilustran varias ara tersti as de C:


El i lo for no es usado para simplemente ontar.
x>>=1 es equivalente a x = x >> 1.
El i lo for iterativamente desplaza a la dere ha x hasta que x se ha e 0.
x & 01 enmas ara el primer bit de x, y si este es 1 enton es in rementa ount.

11.2. Campos de bit


Al ontrario de la mayora de los lenguajes de programa ion, C tiene un metodo prede nido para a eder a un
uni o bit en un byte. Este metodo puede ser utilsimo por una serie de razones:
- Si el alma enamiento es limitado, se pueden alma enar varias variables booleanas en un byte;
- iertas interfa es de dispositivo transmiten informa ion que se odi a en bits dentro de un byte;
- iertas rutinas de en ripta ion ne esitan a eder a los bits en un byte.
El metodo que C usa para a eder a los bits se basa en la estru tura. Un ampo de bit es un tipo espe ial de
estru tura que de ne la longitud en bits que tendra ada elemento. El formato general de una de ni ion de ampo
de bit es:

stru t nomb estru t

tipo nombre 1 : longitud;


tipo nombre 2 : longitud;
.
.
.
tipo nombre n : longitud;

CAPITULO 11. OPERADORES DE BAJO NIVEL Y CAMPOS DE BIT

71

g
Se debe de larar un ampo de bit omo int, unsigned o signed. Se debe de larar los ampos de bits de longitud
1 omo unsigned, ya que un bit uni o no puede tener signo.
Por ejemplo, onsiderar esta de ni ion de estru tura:
stru t empaquetado {
unsigned int b1:1;
unsigned int b2:1;
unsigned int b3:1;
unsigned int b4:1;
unsigned int tipo:4;
unsigned int ent_raro:9;
} paquete;

La estru tura empaquetado ontiene 6 miembros: 4 banderas de 1 bit (b1, b2, b3 y b4), uno de 4 bits (tipo) y
otro de 9 bits (ent raro).
C automati amente empa a los ampos de bit anteriores tan ompa tamente omo sea posible, donde la longitud
maxima del ampo es menor que o igual a la longitud de la palabra entera de la omputadora. Si no fuera el aso,
enton es algunos ompiladores podran permitir traslape en memoria para los ampos, mientras otros podran guardar
el siguiente ampo en la siguiente palabra.
La forma de a esar los miembros es en la forma usual:
paquete.tipo = 7;

Con estru tura anterior se tiene que:


Solamente los n bits mas bajos son asignados a un numero de n bits. Por lo tanto, el ampo tipo
no puede tomar valores mayores que 15, ya que es de 4 bits de largo.
Los ampos de bit son siempre onvertidos a un tipo entero uando se ha e algun al ulo on ellos.
Se permite mez lar los tipos \normales" on los ampos de bit.

11.2.1. Portabilidad
Los ampos de bit son una forma onveniente de expresar mu has opera iones di iles. Sin embargo, los ampos
de bit are en de portabilidad entre plataformas, por alguna de las siguientes razones:
Los enteros podran ser on o sin signo.
Mu hos ompiladores limitan el numero maximo de bits en el ampo de bit al tama~no de un integer,
el ual podra ser de 16 bits o de 32 bits.
Algunos miembros ampos de bit son guardados de izquierda a dere ha, otros son guardados de
dere ha a izquierda en memoria.
Si los ampos de bits son muy largos, el siguiente ampo de bit podra ser guardado onse utivamente
en memoria (traslapando los lmites entre las lo alidades de memoria) o en la siguiente palabra de
memoria.

CAPITULO 11. OPERADORES DE BAJO NIVEL Y CAMPOS DE BIT

72

11.3. Ejer i ios


1. Es ribir una fun ion que muestre un numero de 8 bits (unsigned har) en formato binario.
2. Es ribir una fun ion ponerbits(x,p,n,y) que regrese x, on n bits que empiezan en la posi ion p y estan a
la dere ha de una variable y unsigned har, dejandolos en x en la posi ion p y a la izquierda dejando los otros
bits sin ambio.
Por ejemplo, si x = 10101010 (170 de imal), y = 10100111 (167 de imal), n = 3 y p = 6, enton es se
ne esita tomar 3 bits de de y (111) y ponerlos en x en la posi ion 10xxx 010 para obtener la respuesta 10111010.
La respuesta debera mostrarse en forma binaria (ver primer ejer i io), sin embargo la entrada puede ser en
forma de imal.
La salida podra ser omo la siguiente:
x = 10101010 (binario)
y = 10100111 (binario)
ponerbits n = 3, p = 6 da x = 10111010 (binario)

3. Es ribir una fun ion que invierta los bits de x (unsigned har) y guarde la respuesta en y.
La respuesta debera mostrarse en forma binaria (ver primer ejer i io), sin embargo la entrada puede estar en
forma de imal.
La salida podra ser omo la siguiente:
x = 10101010 (binario)
x invertida = 01010101 (binario)

4. Es ribir una fun ion que rote (no desplaze) a la dere ha n posi iones de bits de x del tipo unsigned har. La
respuesta debera mostrarse en forma binaria (ver primer ejer i io) y la entrada puede ser en forma de imal.
La salida podra ser omo la siguiente:
x = 10100111 (binario)
x rotada por 3 = 11110100 (binario)

Cap
tulo 12

El prepro esador de C
12.1. Dire tivas del prepro esador
Como se omento en el primer aptulo el prepro esamiento es el primer paso en la etapa de ompila ion de un
programa {esta propiedad es uni a del ompilador de C.
El prepro esador tiene mas o menos su propio lenguaje el ual puede ser una herrramienta muy poderosa para el
programador. Todas las dire tivas de prepro esador o omandos ini ian on un #.
Las ventajas que tiene usar el prepro esador son:
- los programas son mas fa iles de desarrollar,
- son mas fa iles de leer,
- son mas fa iles de modi ar
- y el odigo de C es mas transportable entre diferentes arquite turas de maquinas.

12.1.1.

#define

El prepro esador tambien permite on gurar el lenguaje. Por ejemplo, para ambiar a las senten ias de bloque
de odigo { ... } delimitadores que haya inventado el programador omo ini io ... fin se puede ha er:
#define ini io {
#define fin }

Durante la ompila ion todas las o urren ias de ini io y fin seran reemplazadas por su orrespondiente { o }
delimitador y las siguientes etapas de ompila ion de C no en ontraran ninguna diferen ia.
La dire tiva #define se usa para de nir onstantes o ualquier sustitu ion de ma ro. Su formato es el siguiente:

#de ne <nombre de ma ro><nombre de reemplazo>

Por ejemplo:

#define FALSO 0
#define VERDADERO !FALSO

La dire tiva #define tiene otra poderosa ara tersti a: el nombre de ma ro puede tener argumentos. Cada vez
que el ompilador en uentra el nombre de ma ro, los argumentos reales en ontrados en el programa reemplazan los
argumentos aso iados on el nombre de la ma ro. Por ejemplo:

73

CAPITULO 12. EL PREPROCESADOR DE C

74

#define MIN(a,b) (a < b) ? a : b


main()
{
int x=10, y=20;
printf("EL minimo es %d\n", MIN(x,y) );
}

Cuando se ompila este programa, el ompilador sustiuira la expresion de nida por MIN(x,y), ex epto que x e y
seran usados omo los operandos. As despues de que el ompilador ha e la sustitu ion, la senten ia printf sera esta:
printf("El minimo es %d\n", (x < y) ? x : y);

Como se puede observar donde se oloque MIN, el texto sera reemplazado por la de ni ion apropiada. Por lo tanto,
si en el odigo se hubiera puesto algo omo:
x = MIN(q+r,s+t);

despues del prepro esamiento, el odigo podra verse de la siguiente forma:


x = ( q+r < s+t ) ? q+r : s+t;

Otros ejemplos usando #define pueden ser:


#define Deg_a_Rad(X) (X*M_PI/180.0)
/* Convierte grados sexagesimales a radianes, M_PI es el valor de pi */
/*
y esta definida en la bibliote a math.h */
#define IZQ_DESP_8 <<8

La ultima ma ro IZQ DESP 8 es solamente valida en tanto el reemplazo del ontexto es valido, por ejemplo: x =

y IZQ DESP 8.

El uso de la sustitu ion de ma ros en el lugar de las fun iones reales tiene un bene io importante: in rementa
la velo idad del odigo porque no se penaliza on una llamada de fun ion. Sin embargo, se paga este in remento de
velo idad on un in remento en el tama~no del programa porque se dupli a el odigo.

12.1.2. #undef
Se usa #undef para quitar una de ni ion de nombre de ma ro que se haya de nido previamente. El formato
general es:

#undef <nombre de ma ro>

El uso prin ipal de #undef es permitir lo alizar los nombres de ma ros solo en las se iones de odigo que los
ne esiten.

12.1.3. #in lude


La dire tiva del prepro esador #in lude instruye al ompilador para in luir otro ar hivo fuente que esta dado
on esta dire tiva y de esta forma ompilar otro ar hivo fuente. El ar hivo fuente que se leera se debe en errar entre
omillas dobles o parentesis de angulo. Por ejemplo:

CAPITULO 12. EL PREPROCESADOR DE C

75

#in lude <ar hivo>


#in lude "ar hivo"

Cuando se indi a <ar hivo> se le di e al ompilador que busque donde estan los ar hivos in luidos o \in lude"
del sistema. Usualmente los sistemas on UNIX guardan los ar hivos en el dire torio /usr/in lude.
Si se usa la forma "ar hivo" es bus ado en el dire torio a tual, es de ir, donde el programa esta siendo eje utado.
Los ar hivos in luidos usualmente ontienen los prototipos de las fun iones y las de lara iones de los ar hivos
abe era (header les) y no tienen odigo de C (algoritmos).

12.1.4. #if In lusion ondi ional


La dire tiva #if evalua una expresion onstante entera. Siempre se debe terminar on #endif para delimitir el
n de esta senten ia.
Se pueden as mismo evaluar otro odigo en aso se umpla otra ondi ion, o bien, uando no se umple ninguna
usando #elif o #else respe tivamente.
Por ejemplo,
#define MEX 0
#define EUA 1
#define FRAN 2
#define PAIS_ACTIVO MEX
#if PAIS_ACTIVO == MEX
har moneda[="pesos";
#elif PAIS_ACTIVO == EUA
har moneda[="dolar";
#else
har moneda[="fran o";
#endif

Otro metodo de ompila ion ondi ional usa las dire tivas #ifdef (si de nido) y #ifndef (si no de nido).
El formato general de #ifdef es:

#ifdef <nombre de ma ro>

<se uen ia de sente ias>

#endif

Si el nombre de ma ro ha sido de nido en una senten ia #de ne, se ompilara la se uen ia de sente ias entre
el #ifdef y #endif.
El formato general de #ifdef es:

#ifndef <nombre de ma ro>

<se uen ia de sente ias>

#endif

Las dire tivas anteriores son utiles para revisar si las ma ros estan de nidas | tal vez por modulos diferentes o
ar hivos de abe era.
Por ejemplo, para poner el tama~no de un entero para un programa portable entre TurboC de DOS y un sistema
operativo on UNIX, sabiendo que TurboC usa enteros de 16 bits y UNIX enteros de 32 bits, enton es si se quiere
ompilar para TurboC se puede de nir una ma ro TURBOC, la ual sera usada de la siguiente forma:

CAPITULO 12. EL PREPROCESADOR DE C

76

#ifdef TURBOC
#define INT_SIZE 16
#else
#define INT_SIZE 32
#endif

12.2. Control del prepro esador del ompilador


Se puede usar el ompilador g para ontrolar los valores dados o de nidos en la lnea de omandos. Esto permite
alguna exibilidad para on gurar valores ademas de tener algunas otras fun iones utiles. Para lo anterior, se usa la
op ion -Dma ro[=defn, por ejemplo:
g -DLONGLINEA=80 prog. -o prog

que hubiese tenido el mismo resultado que


#define LONGLINEA 80

en aso de que hubiera dentro del programa (prog. ) algun #define o #undef pasara por en ima de la entrada
de la lnea de omandos, y el ompilador podra mandar un \warning" sobre esta situa ion.
Tambien se puede poner un smbolo sin valor, por ejemplo:
g -DDEBUG prog. -o prog

En donde el valor que se toma es de 1 para esta ma ro.


Las apli a iones pueden ser diversas, omo por ejemplo uando se quiere omo una bandera para depura ion se
puede ha er algo omo lo siguiente:
#ifdef DEBUG
printf("Depurando: Version del programa 1.0\n");
#else
printf("Version del programa 1.0 (Estable)\n");
#endif

Como los omandos del prepro esador pueden estar en ualquier parte de un programa, se pueden ltrar variables
para mostrar su valor, uando se esta depurando, ver el siguiente ejemplo:
x = y * 3;
#ifdef DEBUG
printf("Depurando: variables x e y iguales a \n",x,y);
#endif

La op ion -E ha e que la ompila ion se detenga despues de la etapa de prepro esamiento, por lo anterior no se
esta propiamente ompilando el programa. La salida del prepro esamiento es enviada a la entrada estandar. GCC
ignora los ar hivos de entrada que no requieran prepro esamiento.

12.3. Otras dire tivas del prepro esador


La dire tiva #error forza al ompilador a parar la ompila ion uando la en uentra. Se usa prin ipalmente para
depura ion. Por ejemplo:

CAPITULO 12. EL PREPROCESADOR DE C

77

#ifdef OS_MSDOS
#in lude <msdos.h>
#elifdef OS_UNIX
#in lude "default.h"
#else
#error Sistema Operativo in orre to
#endif

La dire tiva #line numero \ adena" informa al prepro esador ual es el numero siguiente de la lnea de entrada.
Cadena es op ional y nombra la siguiente lnea de entrada. Esto es usado fre uentemente uando son tradu idos otros
lenguajes a C. Por ejemplo, los mensajes de error produ idos por el ompilador de C pueden referen iar el nombre
del ar hivo y la lnea de la fuente original en vez de los ar hivos intermedios de C.
Por ejemplo, lo siguiente espe i a que el ontador de lnea empezara on 100.
#line 100 "test. "
/* ini ializa el ontador de linea y nombre de ar hivo */
main()
/* linea 100 */
{
printf("%d\n",__LINE__); /* ma ro predefinida, linea 102 */
printf("%s\n",__FILE__); /* ma ro predefinida para el nombre */
}

12.4. Ejer i ios


1. De nir una ma ro min(a,b) para determinar el entero mas peque~no. De nir otra ma ro min3(a,b, ) en
terminos de min(a,b). In orporar las ma ros en un programa demostrativo en donde se pida al usuario tres
numeros y se muestre el mas peque~no.
2. De nir un nombre de ma ro de prepro esador para sele ionar:
los menos signi ativos bits de un unsigned har.
el enesimo bit (asumiendo que el menos signi ativo es 0) de un unsigned har.

Cap
tulo 13

C, UNIX y las bibliote as estandar


Existe una rela ion estre ha entre C y el sistema operativo que eje uta los programas de C. El sistema operativo
UNIX esta es rito en su mayor parte on C. En este aptulo se vera omo C y UNIX intera tuan juntos.
Se usa UNIX para manejar el espa io del ar hivo, para editar, ompilar o eje utar programas, entre otras osas.
Sin embargo UNIX es mu ho mas util que lo anterior.

13.1. Ventajas del usar UNIX on C


Portabilidad Unix o alguna variante de UNIX estan disponibles en mu has maquinas. Los programas es ritos

on UNIX y C estandares deben orrer en ualquier maquina pra ti amente sin ningun problema.

Multiusuario/Multitarea Mu hos programas pueden ompartir la apa idad de pro esamiento de las maquinas.
Manejo de ar hivos El sistema jerarqui o de ar hivos emplea mu has rutinas de manejo de ar hivos.
Programa ion del Shell UNIX suministra un interprete de omandos poderoso que entiende mas de 200 omandos

y que puede tambien orrer UNIX o programas del usuario.

Entubamiento o Pipe Permite la onexion entre programas, en donde la salida de un programa puede ser la

entrada de otro. Lo anterior puede ha er e desde la lnea de omandos o dentro de un programa de C.

Utileras de UNIX Hay er a de 200 utileras que permiten eje utar mu has rutinas sin es ribir nuevos programas.

Por ejemplo: make, grep di , awk, et .

Llamadas al sistema UNIX tiene aproximadamente 60 llamadas al sistema, que son el orazon del sistema
operativo o del kernel de UNIX. Las llamadas estan a tualmente es ritas en C. Todas ellas pueden ser a esadas

desde programas de C. Ejemplos de estas son el sistema basi o de E/S, a eso al reloj del sistema. La fun ion
open() es un ejemplo de una llamada al sistema.

Bibliote a de fun iones Que son adi iones al sistema operativo.

13.2. Uso de fun iones de bibliote as y llamadas del sistema


Para usar las bibliote as de fun iones y las llamadas al sistema en un programa de C simplemente se debe llamar
la fun ion apropiada de C.
Ejemplos de las fun iones de la bibliote a estandar que han sido vistas son las fun iones de E/S de alto nivel
{fprintf(), mallo (), ...

78


CAPITULO 13. C, UNIX Y LAS BIBLIOTECAS ESTANDAR

79

Operadores aritmeti os, generadores de numeros aleatorios | random(), srandom(), lrand48(), drand48(), et .
y fun iones para onversion de adenas a los tipos basi os de C (atoi(), atof(), et .) son miembros de la bibliote a
estandar stdlib.h.
Todas las fun iones matemati as omo sin(), os(), sqrt() son fun iones de la bibliote a estandar de matemati as
(math.h).
Para mu has llamadas del sistema y fun iones de las bibliote as se tiene que in luir el ar hivo abe era apropiado,
por ejemplo: stdio.h, math.h.
Para usar una fun ion se debe asegurar de haber puesto los orrespondientes #in lude en el ar hivo de C. De
esta forma la fun ion puede ser llamada orre tamente.
Es importante asegurarse que los argumentos tengan los tipos esperados, de otra forma la fun ion probablemente
produ ira resultados extra~nos.
Algunas bibliote as requieren op iones extras antes de que el ompilador pueda soportar su uso. Por ejemplo, para
ompilar un programa que in luya fun iones de la bibliote a math.h el omando podra ser de la siguiente forma:
g matprog. -o matprog. -lm

La op ion nal -lm es una instru ion para ligar la bibliote a matemati a on el programa. La pagina de man
para ada fun ion usualmente informa si se requiere alguna bandera de ompila ion espe ial.
Informa ion de asi todas las llamadas al sistema y fun iones de bibliote a estan disponibles en las paginas del
man. Se en uentran disponibles en lnea on tan solo te lear man y el nombre de la fun ion. Por ejemplo:
man drand48

nos dara informa ion a er a de este generador de numeros aleatorios.

Cap
tulo 14

Bibliote a <stdlib.h>
Para usar todas las fun iones de esta bibliote a se debe tener la siguiente dire tiva
#in lude <stdlib.h>

Las fun iones de la bibliote a pueden ser agrupadas en tres ategoras basi as:
Aritmeti as;
Numeros aleatorios; y
Conversion de adenas.
El uso de todas las fun iones es sen illo. Se onsideran dentro del aptulo en forma breve.

14.1. Fun iones aritmeti as


Hay uatro fun iones enteras basi as:
int abs(int j);
long int labs(long int j);
div_t div(int numer, int denom);
ldiv_t ldiv(long int numer, long int denom);

Fundamentalmente hay dos fun iones para enteros y para ompatibilidad on enteros largos.
abs() La fun ion regresa el valor absoluto del argumento entero j.
div() Cal ula el valor numer entre denom y devuelve el o iente y el resto en una estru tura llamada div t que
ontiene dos miembros llamados quot y rem.

La estru tura div t esta de nida en stdlib.h omo sigue:


typedef stru t {
int quot; /* o iente */
int rem; /* residuo */
} div_t;

La estru tura ldiv t es de nida de una forma similar.


Se muestra un ejemplo donde se ha e uso de la fun ion div t:
80

CAPITULO 14. BIBLIOTECA <STDLIB.H>

81

#in lude <stdlib.h>


main()
{
int num=8, den=3;
div_t res;
res = div(num,den);
printf("Respuesta:\n\t Co iente = %d\n\t Residuo = %d\n",
res.quot, res.rem);
}

que genera la siguiente salida:


Respuesta:
Co iente = 2
Residuo = 2

14.2. Numeros aleatorios


Los numeros aleatorios son utiles en programas que ne esitan simular eventos aleatorios, tales omo juegos,
simula iones y experimentos. En la pra ti a ninguna fun ion produ e datos aleatorios verdaderos | las fun iones
produ en numeros pseudo-aleatorios. Los numeros aleatorios son al ulados a partir de una formula dada (los
distintos generadores usan diferentes formulas) y las se uen ias de numeros que son produ idas se repiten. Una
semilla (seed) es usualmente ini ializada para que la se uen ia sea generada. Por lo tanto, si la semilla es siempre
ini ializada on el mismo valor todo el tiempo, el mismo onjunto sera siempre al ulado.
Una te ni a omun para introdu ir mas aleatoriedad en el generador de numeros aleatorios es usando el tiempo
y la fe ha para ini ializar la semilla, ya que este siempre estara ambiando.
Hay mu has fun iones de numeros (pseudo) aleatorios en la bibliote a estandar. Todas ellas operan on la misma
idea basi a pero generan se uen ias diferentes de numeros (basadas en fun iones generadoras diferentes) sobre rangos
diferentes de numeros.
El onjunto mas simple de fun iones es:
int rand(void);
void srand(unsigned int semilla);

rand() La fun ion devuelve un entero pseudo-aleatorio entre 0 y 215

1 (RAND MAX).

srand() Estable e su argumento omo la semilla de una nueva serie de enteros pseudo-aleatorios.

Un ejemplo sen illo del uso del tiempo de la fe ha es ini ializando la semilla a traves de una llamada:
srand( (unsigned int) time( NULL ) );

El siguiente programa tarjeta. muestra el uso de estas fun iones para simular un paquete de tarjetas que esta
siendo revueltas.
/*
** Se usan numeros aleatorios para revolver las "tarjetas" de la baraja.
** El segundo argumento de la fun ion indi a el numero de tarjetas.

CAPITULO 14. BIBLIOTECA <STDLIB.H>

** La primera vez que esta fun ion es llamada, srand es


** llamada para ini ializar el generador de numeros aleatorios.
*/
#in lude <stdlib.h>
#in lude <time.h>
#define VERDADERO
1
#define FALSO 0
void inter ambiar( int *baraja, int n_ artas )
{
int
i;
stati int
primera_vez = VERDADERO;
/*
** Ini ializar el generador de numeros on la fe ha a tual
** si aun no se ha he ho.
*/
if( primera_vez ){
primera_vez = FALSO;
srand( (unsigned int)time( NULL ) );
}
/*
** "inter ambiar" empleando pares de artas.
*/
for( i = n_ artas - 1; i > 0; i -= 1 ){
int
alguno;
int
temp;
alguno = rand() % i;
temp = baraja[ alguno ;
baraja[ alguno = baraja[ i ;
baraja[ i = temp;
}
}

14.3. Conversion de adenas


Existen unas uantas fun iones para onvertir adenas a enteros, enteros largos y valores otantes. Estas son:

double atof( onst har * adena) Convierte una adena a un valor otante.
int atoi( onst har * adena) Convierte una adena a un valor entero.
int atol( onst har * adena) Convierte una adena a un valor entero largo.
double strtod( onst har * adena, har ** nap) Convierte una adena a un valor de punto otante.

82

CAPITULO 14. BIBLIOTECA <STDLIB.H>

83

double strtol( onst har * adena, har * nap, int base) Convierte una adena a un entero largo de
a uerdo a una base dada, la ual debera estar entre 2 y 36 in lusive.

unsigned long strtoul( onst har * adena, har * nap, int base) Convierte una adena a un entero
largo sin signo.

Varias de las fun iones se pueden usar en forma dire ta, por ejemplo:
har
har
har
har
har
har
har

* ad1 =
* ad2 =
* ad3 =
* ad4 =
* ad5 =
* ad6 =
* ad7;

"100";
"55.444";
"
1234";
"123 uatro";
"invalido123";
"123E23Hola";

int i;
float f:
i
f
i
i
i
f

=
=
=
=
=
=

atoi( ad1);
/* i =
atof( ad2);
/* f =
atoi( ad3);
/* i =
atoi( ad4);
/* i =
atoi( ad5);
/* i =
strtod( ad6, & ad7);

100 */
55.44 */
1234 */
123 */
0 */
/* f=1.230000E+25 y ad7=hola*/

Nota:
Los ara teres en blan o son saltados.
Cara teres ilegales son ignorados.
Si la onversion no puede ser he ha se regresa ero y errno es puesta on el valor ERANGE.

14.4. Busqueda y ordenamiento


La bibliote a stdlib.h tiene dos fun iones utiles para ha er busqueda y ordenamiento de datos de ualquier tipo.
La fun ion qsort() ya fue vista previamente en la se ion 10.3.
Para ompletar la lista se anota el prototipo, pero para ver un ejemplo pasar al aptulo indi ado.
La fun ion qsort de la bibliote a estandar es muy util, ya que esta dise~nada para ordenar un arreglo por un valor
llave de ualquier tipo en orden as endente, on tal de que los elementos del arreglo sean de un tipo jo.
El prototipo de la fun ion de a uerdo a stdlib.h es:
void qsort(void *base, size_t nmiemb, size_t tam,
int (* ompar)( onst void *, onst void *));

Similarmente, hay una fun ion para busqueda binaria, bsear h() la ual tiene el siguiente prototipo en stdlib.h
omo:
void *bsear h( onst void *key, onst void *base, size_t nmemb,
size_t size, int (* ompar)( onst void *, onst void *));

A ontinua ion se muestra un ejemplo que ha e uso de la fun ion bsear h():

CAPITULO 14. BIBLIOTECA <STDLIB.H>

84

#define TAM 10
#in lude <stdio.h>
#in lude <stdlib.h>
typedef stru t {
int llave;
har informa ion[30;
} Registro;
int ompara_registro(void onst *i, void onst *j)
{
int a, b;
a = ((Registro *) i)->llave;
b = ((Registro *) j)->llave;
return a - b;
}
main()
{
Registro llave;
Registro *resp;
Registro arreglo[TAM;
int long_arreglo = TAM;
arreglo[0.llave
arreglo[3.llave
arreglo[6.llave
arreglo[9.llave

=
=
=
=

-43; arreglo[1.llave = -9; arreglo[2.llave = 0;


3; arreglo[4.llave = 4; arreglo[5.llave = 9;
10; arreglo[7.llave = 12; arreglo[8.llave = 30;
203;

printf("Introdu e el valor de la llave que se bus ara en el arreglo: ");


s anf("%d",&llave.llave); /* valor del indi e que sera bus ado */
resp = (Registro *) bsear h(&llave, arreglo, long_arreglo, sizeof(Registro),
ompara_registro);
if (resp != NULL )
printf("Se lo alizo la llave %d\n",resp->llave);
else
printf("No se lo alizo ningun elemento on la llave %d\n", llave.llave);
}

La fun ion bsear h() regresa un apuntador al registro que oin ide on la llave dada, o bien, el valor NULL si no
en uentra el registro.
Observar que el tipo del argumento de la llave debe ser del mismo tipo que la del arreglo de los elementos (en
nuestro aso Registro).

CAPITULO 14. BIBLIOTECA <STDLIB.H>

85

14.5. Ejer i ios


1. Es ribir un programa que simule el lanzamiento de un dado.
2. Es ribir un programa que simule el melate, en donde se sele ionan 6 numeros enteros en un rango de 1 al 44
3. Es ribir un programa que lea un numero de la lnea de entrada y genere un numero otante aleatorio en el
rango de 0 a el numero de entrada.

Cap
tulo 15

Bibliote a <math.h>
La bibliote a de matemati as es relativamente fa il de usar, al igual que las vistas previamente. Se debe in luir
la dire tiva de prepro esamiento #in lude <math.h>, ademas de re ordar de ligar la bibliote a de matemati as al
ompilar:
g progmat. -o progmat -lm

Un error omun es el olvidar in luir el ar hivo <math.h>.

15.1. Fun iones matemati as


Se muestra a ontinua ion una lista de fun iones matemati as. Son fa iles de usar y algunas de ellas han sido ya
usadas previamente. No se propor iona ejemplo de las mismas.
double a os(double x) Cal ula el ar o oseno de x.
double asin(double x) Cal ula el ar o seno de x.
double atan(double x) Devuelve el ar o tangente en radianes.
double atan2(double y, double x) Cal ula el ar o tangente de las dos variables x e y. Es similar a al ular

el ar o tangente de y / x, ex epto en que los signos de ambos argumentos son usados para determinar el
uadrante del resultado.
double eil(double x) Redondea x ha ia arriba al entero mas er ano.
double os(double x) devuelve el oseno de x, donde x esta dado en radianes.
double osh(double x) Devuelve el oseno hiperboli o de x.
double exp(double x) Devuelve el valor de e (la base de los logaritmos naturales) elevado a la poten ia x.
double fabs(double x) Devuelve el valor absoluto del n
umero en punto otante x.
double floor(double x) Redondea x ha ia abajo al entero mas er ano.
double fmod(double x, double y) Cal ula el resto de la division de x entre y. El valor devuelto es x - n * y,

donde n es el o iente de x / y.

double frexp(double x, int *exp) Se emplea para dividir el n


umero x en una fra ion normalizada y un
exponente que se guarda en exp x = res  2exp .

86

CAPITULO 15. BIBLIOTECA <MATH.H>

87

long int labs(long int j) Cal ula el valor absoluto de un entero largo.
double ldexp(double x, int exp) Devuelve el resultado de multipli ar el n
umero x por 2 elevado a exp
(inversa de frexp).
double log(double x); Devuelve el logaritmo neperiano de x.
double log10(double x) Devuelve el logaritmo de imal de x.
double modf(double x, double *iptr) Divide el argumento x en una parte entera y una parte fra ional.

La parte entera se guarda en iptr.

double pow(double x, double y) Devuelve el valor de x elevado a y.


double sin(double x) Devuelve el seno de x.
double sinh(double x) Regresa el seno hiperboli o de x.
double sqrt(double x) Devuelve la raz uadrada no negativa de x.
double tan(double x) Devuelve la tangente de x.
double tanh(double x) Devuelve la tangente hiperboli a de x.

15.2. Constantes matemati as


La bibliote a de matemati as de ne varias onstantes (por lo general dese hadas). Siempre es a onsejable usar
estas de ni iones.
M_E La base de los logaritmos naturales e.
M_LOG2E El logaritmo de e de base 2.
M_LOG10E El logaritmo de e de base 10.
M_LN2 El logartimo natural de 2.
M_LN10 El logaritmo natural de 10.
M_PI 
M_PI_2 =2
M_PI_4 =4
M_1_PI 1=
M_2_PI 2=

M_2_SQRTPI 2= 
M_SQRT2 La raz uadrada positiva de 2
M_SQRT1_2 La raz uadrada positiva de 1/2

Cap
tulo 16

Entrada y salida (E/S) stdio.h


En este aptulo se veran varias formas de entrada y salida (E/S). Se han men ionado brevemente algunas formas
y ahora se revisaran on un po o mas de detalle.
Los programas que hagan uso de las fun iones de la bibliote a de E/S deben in luir la abe era, esto es:
#in lude <stdio.h>

16.1. Reportando errores


En mu has o asiones es util reportar los errores en un programa de C. La fun ion de la bibliote a estandar perror
es la indi ada para ha erlo. Es usada onjuntamente on la variable errno y fre uentemente uando se en uentra un
error se desea terminar el programa antes. Ademas se revisa la fun ion exit() y errno, que en un sentido estri to
no son parte de la bibliote a stdio.h, para ver omo trabajan on perror.

16.1.1. perror()
El prototipo de la fun ion perror es:
void perror( onst har *s);

La fun ion perror() produ e un mensaje que va a la salida estandar de errores, des ribiendo el ultimo error
en ontrado durante una llamada al sistema o a iertas fun iones de bibliote a. La adena de ara teres s que se pasa
omo argumento, se muestra primero, luego un signo de dos puntos y un espa io en blan o; por ultimo, el mensaje y
un salto de lnea. Para ser de mas utilidad, la adena de ara teres pasada omo argumento debera in luir el nombre
de la fun ion que in urrio en el error. El odigo del error se toma de la variable externa errno, que toma un valor
uando o urre un error, pero no es puesta a ero en una llamada no erronea.

16.1.2. errno
A la variable espe ial del sistema errno algunas llamadas al sistema (y algunas fun iones de bibliote a) le dan un
valor entero, para indi ar que ha habido un error. Esta variable esta de nida en la abe era #in lude <errno.h> y
para ser usada dentro de un programa debe ser de larada de la siguiente forma:
extern int errno;

El valor solo es signi ativo uando la llamada devolvio un error (usualmente -1), algunas ve es una fun ion
tambien puede devolver -1 omo valor valido, por lo que se debe poner errno a ero antes de la llamada, para poder
dete tar posibles errores.
88

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

89

16.1.3. exit
La fun ion exit tiene el siguiente prototipo de a uerdo a la abe era #in lude <stdlib.h>:
void exit(int status);

La fun ion produ e la termina on normal del programa y la devolu ion de status al pro eso padre o al sistema
operativo. El valor de status es usado para indi ar omo ha terminado el programa:
o sale on un valor EXIT_SUCCESS en una termina ion
o sale on un valor EXIT_FAILURE en una termina ion
Por lo tanto uando se en uentre un error se llamara a la fun ion omo exit(EXIT_FAILURE) para terminar un
programa on errores.

16.2. Flujos
Los ( ujos) son una forma exible y e iente para leer y es ribir datos.
Existe una estru tura interna de C, FILE, la ual representa a todas los ujos y esta de nida en stdio.h. Por lo
tanto simplemente se ne esita referirse a la estru tura para realizar entrada y salida de datos.
Para usar los ujos enton es se debe de larar una variable o apuntador de este tipo en el programa. No se requiere
ono er mas detalles a er a de la de ni ion. Se debe abrir un ujo antes de realizar ualquier E/S, despues se puede
a esar y enton es se ierra.
El ujo de E/S usa un BUFFER, es de ir, un pedazo jo de area temporal de la memoria (el bu er) es ledo o
es rito a un ar hivo. Lo siguiente se muestra en la gura 17.1. Observar que el apuntador del ar hivo a tualmente
apunta a este bu er.
Dispositivo de Almacenamiento
Archivo o disco

Sistema Operativo

01
1010
10
10
1010
10
1010
1010
1010
1010
10
1010
1010
1010
1010
1010
1010
10

Buffer

Base del buffer


Apuntador de archivo

Figura 16.1: Modelo de entrada salida usando un bu er.


Esto ondu e a un uso e iente de E/S pero se debe tener uidado: los datos es ritos a un bu er no apare en en
un ar hivo (o dispositivo) hasta que el bu er es es rito ( on \n se puede ha er). Cualquier salida anormal del odigo
puede ausar problemas.

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

90

16.2.1. Flujos prede nidos


En UNIX se tienen prede nidos 3 ujos (en stdio.h): stdin, stdout y stderr.
Todas ellas usan texto omo metodo de E/S.
Los ujos stdin y stdout pueden ser usadas on ar hivos, programas, dispositivos de E/S omo el te lado, la
onsola, et . El ujo stderr siempre va a la onsola o la pantalla.
La onsola es el dispositivo prede nido para stdout y stderr. El te lado lo es para stdin.
Los ujos prede nidos son automati amente abiertas.

Redire ionamiento
Lo siguiente no es parte de C, pero depende del sistema operativo. Se ha e redire ionamiento desde la lnea de
omandos on:
> que redire iona stdout a un ar hivo.
Por lo tanto, si se tiene un programa llamado salida, que usualmente muestra en pantalla algo, enton es:
salida > ar hivo_sal

mandara la salida al ar hivo ar hivo sal


< redire iona stdin desde un ar hivo a un programa.
Por lo tanto, si se espera entrada desde el te lado para un programa llamado entrada, se puede leer en forma
similar la entrada desde un ar hivo.
entrada < ar hivo_ent
Con | entubamiento o pipe se olo a stdout de un programa en stdin de otro,
prog1 | prog2

Por ejemplo, mandar la salida (usualmente a onsola) de un programa dire tamente a la impresora
out | lpr

16.3. E/S Basi a


Hay un par de fun iones que dan las fa ilidades basi as de E/S. Quizas las mas omunes son: get har() y
put har(). Estan de nidas y son usadas omo sigue:
int get har(void) | lee un ara ter de stdin
int put har( har h) | es ribe un ara ter a stdout y regresa el ara ter es rito.
main() {
int h;
h = get har();
(void) put har(( har) h); }

Otras fun iones rela ionadas son:


int get (FILE *flujo);
int put ( har h, FILE *flujo);

16.4. E/S formateada


Se han visto ya algunos ejemplos de omo C usa la E/S formateada. En esta se ion se revisaran on mas detalle.

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

91

16.4.1. printf
El prototipo de la fun ion esta de nido omo:
int printf( onst har *formato, lista arg ...);

que muestra en stdout la lista de argumentos de a uerdo al formato espe i ado. La fun ion devuelve el numero
de ara teres impresos.
La adena de formateo tiene dos tipos de objetos:
ara teres ordinarios | estos son opiados a la salida.
espe i adores de onversion | pre edidos por % y listados en la tabla 16.1.
Espe i ador ( %)

Tipo

Resultado


i,d
o
x,X

har
int
int
int

u
s

int
har *

f
e,E

double/ oat
"

g,G

"

un solo ara ter


numero base diez
numero base o ho
numero base die iseis
nota ion minus/mayus
entero sin signo
impresion de adena
terminada por nulo
formato -m.ddd ...
Nota ion Cient a
-1.23e002
e o f la que sea
mas ompa ta
ara ter %

Cuadro 16.1: Cara teres de format printf/s anf


Entre el % y el ara ter de formato se puede poner:
- signo menos para justi ar a la izquierda.
numero entero para el an ho del ampo.
m.d en donde m es el an ho del ampo, y d es la pre ision de dgitos despues del punto de imal o el

numero de ara teres de una adena.


Por lo tanto:
printf("%-2.3f\n",17.23478);

la salida en pantalla sera:


17.235

y
printf("VAT=17.5%%\n");

genera la siguiente salida:


VAT=17.5%

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

92

16.4.2. s anf
La fun ion esta de nida omo sigue:
int s anf( onst har *formato, lista arg ...);

Lee de la entrada estandar (stdin) y olo a la entrada en la dire ion de las variables indi adas en lista args.
Regresa el numero de ara teres ledos.
La adena de ontrol de formateo es similar a la de printf.
Importante: se requiere la dire ion de la variable o un apuntador on s anf.
Por ejemplo:
s anf("%d", &i);

Para el aso de un arreglo o adena solo se requiere el nombre del mismo para poder usar s anf ya que orresponde
al ini io de la dire ion de la adena.
har adena[80;
s anf("%s", adena);

16.5. Ar hivos
Los ar hivos son la forma mas omun de los ujos.
Lo primero que se debe ha er es abrir el ar hivo. La fun ion fopen() ha e lo siguiente:
FILE *fopen( onst har *nomb, onst har *modo);
fopen regresa un apuntador a un FILE. En la adena nomb se pone el nombre y la traye toria del ar hivo que se
desea a esar. La adena modo ontrola el tipo de a eso. Si un ar hivo no puede ser a esado por alguna razon un
apuntador NULL es devuelto.

Los modos son:

\r " le tura;
\w " es ritura; y
\a "
Para abrir un ar hivo se debe tener un ujo (apuntador tipo ar hivo) que apunte a la estru tura FILE.
Por lo tanto, para abrir un ar hivo denominado miar h.dat para le tura haremos algo omo lo siguiente;
FILE *flujo; /* Se de lara un flujo */
flujo = fopen("miar h.dat","r");

es una buena pra ti a revisar si un ar hivo se pudo abrir orre tamente


if ( (flujo = fopen("miar h.dat","r")) == NULL )
{
printf("No se pudo abrir %s\n","miar h.dat");
exit(1);
}
.....

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

93

16.5.1. Le tura y es ritura de ar hivos


Las fun iones fprintf y fs anf son omunmente empleadas para a esar ar hivos.
int fprintf(FILE *flujo, onst har *formato, args ... );
int fs anf(FILE *flujo, onst har *formato, args ... );

Las fun iones son similares a printf y s anf ex epto que los datos son ledos desde el ujo, el ual debera ser
abierto on fopen().
El apuntador al ujo es automati amente in rementado on todas las fun iones de le tura y es ritura. Por lo
tanto, no se debe preo upar en ha er lo anterior.
har * adena[80;
FILE *flujo;
if ( (flujo = fopen( ... )) != NULL)
fs anf(flujo,"%s", adena);

Otras fun iones para ar hivos son:


int get (FILE *flujo) int fget (FILE *flujo)
int put ( har h, FILE *s) int fput ( har h, FILE *s)

Estas son pare idas a get har y put har.


get esta de nida omo una ma ro del prepro esador en stdio.h. fget es una fun ion de la bibliote a de C.
Con ambas se onsigue el mismo resultado.
Para el vol ado de los datos de los ujos a dis o, o bien, para disaso iar un ujo a un ar hivo, ha iendo previamente
un vol ado, usar:
int fflush(FILE *flujo);
int f lose(FILE *flujo);

Tambien se puede tener a eso a los ujos predeterminados on fprintf, et . Por ejemplo:
fprintf(stderr,"<<No se puede al ular!!\n");
fs anf(stdin,"%s",string);

16.6. sprintf y ss anf


Son pare idas a fprintf y fs anf ex epto que es riben/leen una adena.
int sprintf( har * adena, har *formato, args ... )
int ss anf( har * adena, ahr *formato, args ... )

Por ejemplo:
float tanque_lleno = 47.0; /* litros */
float kilometros = 400;
har km_por_litro[80;
sprintf( km_por_litro, "Kilometros por litro = %2.3f", kilometros/tanque_lleno);

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

94

16.6.1. Peti ion del estado del ujo


Existen unas uantas fun iones utiles para ono er el estado de algun ujo y que tienen los prototipos siguientes:
int feof(FILE *flujo);
int ferror(FILE *flujo);
void learerr(FILE *flujo);
int fileno(FILE *flujo);

feof() devuelve verdadero si el ujo indi ado esta en el n del ar hivo. Por lo tanto para leer un ujo,
fp, lnea a lnea se podra ha er algo omo:
while ( !feof(fp) )
fs anf(fp,"%s",linea);

ferror() inspe iona el indi ador de error para el ujo indi ado, regresando verdadero si un error ha

o urrido.

learerr() limpia los indi adores de n-de- hero y error para el ujo indi ado.
leno() examina el argumento ujo y devuelve su des riptor de hero, omo un entero.

16.7. E/S de bajo nivel o sin alma enamiento intermedio


Esta forma de E/S es sin bu er { ada requerimiento de le tura/es ritura genera un a eso al dis o (o dispositivo)
dire tamente para traer/poner un determinado numero de bytes.
No hay fa ilidades de formateo {ya que se estan manipulando bytes de informa ion.
Lo anterior signi a que se estan usando ar hivos binarios (y no de texto).
En vez de manejar apuntadores de ar hivos, se emplea un manejador de ar hivo de bajo nivel o des riptor de
ar hivo, el ual da un entero uni o para identi ar ada ar hivo.
Para abrir un ar hivo usar:
int open( har* nomb, int flag);

que regresa un des riptor de ar hivo o -1 si falla.

flag ontrola el a eso al ar hivo y tiene los siguientes ma ros de nidas en f ntl.h:

O APPEND el ar hivo se abrira en modo de solo a~nadir


O CREAT si el ar hivo no existe, sera reado.
O EXCL abrir en forma ex lusiva.
O RDONLY solo le tura
O RDWR le tura y es ritura
O WRONLY solo es ritura

para ver otras op iones usar man.


La fun ion:
int reat( har* nomb, int perms);

puede tambien ser usada para rear un ar hivo.


Otras fun iones son:
int lose(int fd);
int read(int fd, har *buffer, unsigned longitud);
int write(int fd, har *buffer, unsigned longitud);

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

95

que pueden ser usadas para errar un ar hivo y leer/es ribir un determinado numero de bytes de la memoria/ha ia
un ar hivo en la lo alidad de memoria indi ada por buffer.
La fun ion sizeof() es omunmente usada para indi ar la longitud.
Las fun iones read y write regresan el numero de bytes ledos/es ritos o -1 si fallan.
Se tiene a ontinua ion dos apli a iones que usan algunas de las fun iones indi adas:
#in lude
#in lude
#in lude
#in lude

<stdio.h>
<sys/types.h>
<sys/stat.h>
<f ntl.h>

main(int arg , har **argv)


{
float buffer[={23.34,2.34,1112.33};
int df;
int bytes_es ;
int num_flot;
/* Primeramente se rea el ar hivo */
if ( (df = open(argv[1, O_CREAT, S_IRUSR | S_IWUSR) ) == -1)
{ /* Error, ar hivo no abierto */
perror("Ar hivo datos, apertura");
exit(1);
}
else
printf("Des riptor de ar hivo %d\n",df);
/* Despues se abre para solamente es ribir */
if ( (df = open(argv[1, O_WRONLY) ) == -1)
{ /* Error, ar hivo no abierto */
perror("Ar hivo datos, apertura");
exit(1);
}
else
printf("Des riptor de ar hivo %d\n",df);

/* En primer lugar se es ribe el numero de flotantes que seran es ritos */


num_flot = 3;
if ( (bytes_es = write(df, &num_flot, sizeof(int)) ) == -1)
{ /* Error en la es ritura */
perror("Ar hivo datos, es ritura");
exit(1);
}
else
printf("Es ritos %d bytes\n",bytes_es );

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

96

/* Se es ribe el arreglo de flotantes */


if ( (bytes_es = write(df, buffer, num_flot*sizeof(float)) ) == -1)
{ /* Error en la es ritura */
perror("Ar hivo datos, es ritura");
exit(1);
}
else
printf("Es ritos %d bytes\n",bytes_es );
lose(df);
}

Ejemplo de le tura del ejemplo anterior:


/*
/*
/*
/*

Este programa lee una lista de flotantes de un ar hivo binario.


El primer byte del ar hivo es un entero indi ando uantos
flotantes hay en el ar hivo. Los flotantes estan despues del
entero, el nombre del ar hivo se da en la linea de omandos.

*/
*/
*/
*/

#in lude <stdio.h>


#in lude <f ntl.h>
main(int arg , har **argv)
{
float buffer[1000;
int fd;
int bytes_leidos;
int num_flot;
if ( (fd = open(argv[1, O_RDONLY)) == -1)
{ /* Error, ar hivo no abierto */
perror("Ar hivo datos");
exit(1);
}
if ( (bytes_leidos = read(fd, &num_flot, sizeof(int))) == -1)
{ /* Error en la le tura */
exit(1);
}
if ( num_flot > 999 ) { /* ar h muy grande */ exit(1); }
if ( (bytes_leidos = read(fd, buffer, num_flot*sizeof(float))) == -1)
{ /* Error en la le tura */
exit(1);
}

CAPITULO 16. ENTRADA Y SALIDA (E/S) STDIO.H

97

16.8. Ejer i ios


1. Es ribir un programa para opiar un ar hivo en otro. Los 2 nombres de los ar hivos son dados omo los primeros
argumentos del programa.
Copiar bloques de 512 bytes ada vez.

Revisar que el programa:


- tenga dos argumentos o mostrar "El programa requiere dos argumentos";
- el primer nombre de ar hivo sea de le tura o mostrar "No se puede abrir ar hivo ... para le tu
- que el segundo nombre del ar hivo sea de es ritura o mostrar "No se puede abrir ar hivo ... pa

2. Es ribir un programa ultimas"que muestre las ultimas n lneas de un ar hivo de texto. n y el nombre del
ar hivo deberan espe i arse desde la lnea de omandos. Por defe to n debera ser 5. El programa debera ha er
el mejor uso del espa io de alma enamiento.
3. Es ribir un programa que ompare dos ar hivos y muestre las lneas que di eran. Tip: bus ar rutinas apropiadas
para manejo de adenas y manejo de ar hivos. El programa no debera ser muy grande.

Cap
tulo 17

Manejo de adenas <string.h>


Re ordando la presenta ion de arreglos he ha ( aptulo 5) en donde las adenas estan de nidas omo un arreglo
de ara teres o un apuntador a una por ion de memoria onteniendo ara teres ASCII. Una adena en C es una
se uen ia de ero o mas ara teres seguidas por un ara ter NULL o \0:
DESCRIPCION
F

A C U

D .........

\0
49

Figura 17.1: Representa ion de un arreglo.


Es importante preservar el ara ter de termina ion NULL, ya que on este es omo C de ne y maneja las longitudes
de las adenas. Todas las fun iones de la bibliote a estandar de C lo requieren para una opera ion satisfa toria.
En general, aparte de algunas fun iones restringidas en longitud (strn at(), strn mp() y strn py()), al menos
que se reen adenas a mano, no se deberan en ontrar problemas. Se deberan usar las fun iones para manejo de
adenas y no tratar de manipular las adenas en forma manual desmantelando y ensamblando adenas.

17.1. Fun iones basi as para el manejo de adenas


Todas las fun iones para manejo de adenas tienen su prototipo en:
#in lude <string.h>

Las fun iones mas omunes son des ritas a ontinua ion:
har *str py( onst har *dest, onst har *orig) | Copia la adena de ara teres apuntada por orig
(in luyendo el ara ter terminador '\0') al ve tor apuntado por dest. Las adenas no deben sola-

parse, y la de destino, debe ser su ientemente grande omo para alojar la opia.

int str mp( onst har *s1, onst har *s2) | Compara las dos adenas de ara teres s1 y s2. Devuelve
un entero menor, igual o mayor que ero si se en uentra que s1 es, respe tivamente, menor que, igual
a, o mayor que s2.
har *strerror(int errnum) | Devuelve un mensaje de error que orresponde a un numero de error.
int strlen( onst har *s) | Cal ula la longitud de la adena de ara teres.
har *strn at( har *s1, onst har *s2, size t n) | Agrega n ara teres de s2 a s1.
int strn mp( onst har *s1, har *s2, size t n) | Compara los primeros n ara teres de dos adenas.

98

CAPITULO 17. MANEJO DE CADENAS <STRING.H>

99

har *strn py( onst har *s1, onst har *s2, size t n) | Copia los primeros n ara teres de s2 a s1.
str ase mp( onst har *s1, onst har *s2) | version que ignora si son mayus ulas o minus ulas de
str mp().
strn ase mp( onst har *s1, onst har *s2, size t n) | version insensible a mayus ulas o minus ulas
de strn mp() que ompara los primeros n ara teres de s1.

El uso de mu has fun iones es dire to, por ejemplo:


har *s1 = "Hola";
har *s2;
int longitud;
longitud = strlen("Hola"); /* long = 4 */
(void) str py(s2,s1);

Observar que tanto str at() y str opy() regresan una opia de su primer argumento, el ual es el arreglo
destino. Observar tambien que orden de los argumentos es arreglo destino seguido por arreglo fuente lo ual a ve es
es una situa ion para ha erlo in orre tamente.
La fun ion str mp() ompara lexi ogra amente las dos adenas y regresa:
Menor que ero | si s1 es lexi amente menor que s2;
Cero | si s1 y s2 son lexi amente iguales;
Mayor que ero | si s1 es lexi amente mayor que s2;

Las fun iones de opiado strn at(), strn mp() y strn py() son versiones mas restringidas que sus ontrapartes
mas generales. Realizan una tarea similar, pero solamente para los primeros n ara teres. Observar que el ara ter
de termina ion NULL podra ser violado uando se usa estas fun iones, por ejemplo:
har *s1 = "Hola";
har *s2 = 2;
int longitud = 2;
(void) strn py(s2, s1, longitud); /* s2 = "Ho" */

donde s2 no tiene el terminador NULL.

17.1.1. Busqueda en adenas


La bibliote a tambien propor iona varias fun iones de busqueda en adenas.
har *str hr( onst har *s, int ) | Devuelve un puntero a la primera o urren ia del ara ter en la
adena de ara teres s.
har *strr hr( onst har *s, int ) | En uentra la ultima o urren ia del ara ter en la adena.
har *strstr( onst har *s1, onst har *s2) | Lo aliza la primera o urren ia de la adena s2 en la

adena s1.

har *strpbrk( onst har *s1, onst har *s2) | Regresa un apuntador a la primera o urren ia en la

adena s1 de ualquier ara ter de la adena s2, o un apuntador nulo si no hay un ara ter de s2
que exista en s1.

CAPITULO 17. MANEJO DE CADENAS <STRING.H>

100

size t strspn( onst har *s1, onst har *s2) | Cal ula la longitud del segmento ini ial de s1 que

onsta uni amente de ara teres en s2.

size t str spn( onst har *s1, onst har *s2) | Regresa el numero de ara teres al prin ipio de s1

que no oin iden on s2.

har *strtok( har *s1, onst har *s2) | Divide la adena apuntada a s1 en una se uen ia de \tokens",
ada uno de ellos esta delimitado por uno o mas ara teres de la adena apuntada por s2.

Las fun iones str hr() y strr hr() son las mas simples de usar, por ejemplo:
har *s1 = "Hola";
har *resp;
resp = str hr(s1,'l');

Despues de la eje u ion, resp apunta a la lo alidad s1 + 2.


La fun ion strpbrk() es una fun ion mas general que bus a la primera o urren ia de ualquier grupo de ara teres, por ejemplo:
har *s1 = "Hola";
har *resp;
res = strpbrk(s1,"aeiou");

En este aso, resp apunta a la lo alidad s1 + 1, la lo alidad de la primera o.


La fun ion strstr() regresa un apuntador a la adena de busqueda espe i ada o un apuntador nulo si la adena
no es en ontrada. Si s2 apunta a una adena de longitud ero (esto es, la adena ), la fun ion regres s1. Por ejemplo:
har *s1 = "Hola";
har *resp;
resp = strstr(s1,"la");

la ual tendra resp = s1 + 2.


La fun ion strtok() es un po o mas ompli ada en uanto a opera ion. Si el primer argumento no es NULL
enton es la fun ion en uentra la posi ion de ualquiera de los ara teres del segundo argumento. Sin embargo, la
posi ion es re ordada y ualquir llamada subse uente a strtok() ini iara en esa posi ion si en estas subse uentes
llamadas el primer argumento no es NULL. Por ejemplo, si deseamos dividir la adena s1 usando ada espa io e
imprimir ada \token" en una nueva lnea haramos lo siguiente:
har s1[ = "Hola mu ha ho grande";
har *t1;
for ( t1 = strtok(s1," ");
t1 != NULL;
t1 = strtok(NULL, " ") )
printf("%s\n",t1);

Se emplea un i lo for en una forma no regular de onteo:


En la ini ializa ion se llama a la fun ion strtok() on la adena s1.
Se termina uando t1 es NULL.
Se esta asignando tokens de s1 a t1 hasta la termina ion llamando a strtok() on el primer
argumento NULL.

CAPITULO 17. MANEJO DE CADENAS <STRING.H>

101

17.2. Prueba y onversion de ara teres < type.h>


Una bibliote a rela ionada #in lude < type.h> la ual ontiene mu has fun iones utiles para onvertir y probar
ara teres individuales.
Las fun iones mas omunes para revisar ara teres tienen los siguientes prototipos:
int isalnum(int ) | Verdad si es alfanumeri o.
int isalpha(int ) | Verdad si es una letra.
int isas ii(int ) | Verdad si es ASCII.
int is ntrl(int ) | Verdad si es un ara ter de ontrol.
int isdigit(int ) | Verdad si es un dgito de imal.
int isgraph(int ) | Verdad si es un ara ter imprimible, ex eptuando el espa io en blan o.
int islower(int ) | Verdad si es una letra minus ula.
int isprint(int ) | Verdad si es un ara ter imprimible, in luyendo el espa io en blan o.
int ispun t(int ) | Verdad si es un signo de puntua ion.
int isspa e(int ) | Verdad si es un espa io
int isupper(int ) | Verdad si es una letra mayus ula.
int isxdigit(int ) | Verdad si es un dgito hexade imal.

Las fun iones para onversion de ara teres son:


int toas ii(int ) | Convierte a ASCII o un unsigned har de 7 bits, borrando los bits altos.
int tolower(int ) | Convierte la letra a minus ulas, si es posible.
int toupper(int ) | Convierte la letra a mayus ulas, si es posible.

El uso de estas fun iones es dire to y por lo tanto, no se dan ejemplos.

17.3. Opera iones on la memoria <memory.h>


Finalmente se vera un resumen de algunas fun iones basi as de memoria. Sin embargo, no son fun iones estri tamente de adenas, pero tienen su prototipo en #in lude <string.h>:
void *mem hr(void *s, int , size t n) | Bus a un ara ter en un bu er.
int mem mp(void *s1, void *s2, size t n) | Compara dos bu ers.
void *mem py(void *dest, void *fuente, size t n) | Copia un bu er dentro de otro.
void *memmove(void *dest, void *fuente, size t n) | Mueve un numero de bytes de un bu er a otro.
void *memset(void *s, int , size t n) | Pone todos los bytes de un bu er a un ara ter dado.

El uso de estas fun iones es dire to y pare ido a las opera iones de ompara ion de ara teres (ex epto que la
longitud exa ta (n) de todas las opera iones debera ser indi ada ya que no hay una forma propia de termina ion).
Observar que en todos los asos bytes de memoria son opiados, por lo que la fun ion sizeof() ayuda en estos
asos, por ejemplo:
har fuente[TAM, dest[TAM;
int ifuente[TAM,idest[TAM;
mem py(dest, fuente, TAM); /* Copia hars (bytes) OK */
mem py(idest,ifuente,TAM*sizeof(int)); /* Copia arreglo de enteros */

CAPITULO 17. MANEJO DE CADENAS <STRING.H>

102

La fun ion memmove() se omporta de la misma forma que mem py() ex epto que las lo alidades de la fuente y
el destino podran traslaparse.
La fun ion mem mp() es similar a str mp() ex epto que unsigned bytes son omparados y se devuelve ero si s1
es menor que s2, et .

17.4. Ejer i ios


1. Es ribir una fun ion similar a strlen que pueda manejar adenas sin terminador. Tip: se ne esitara ono er y
pasar la longitud de la adena.
2. Es ribir una fun ion que regrese verdad, si una adena de entrada es un palndromo. Un palndromo es una
palabra que se lee igual de izquierda a dere ha, o de dere ha a izquierda. Por ejemplo, ANA.
3. Sugerir una posible implementa ion de la fun ion strtok():
a ) usando otras fun iones de manejo de adenas.
b ) desde los prin ipios de apuntadores.

>Como se logra el alma enamiento de una adena separada?


4. Es ribir una fun ion que onvierta todos los ara teres de una adena a mayus ulas.
5. Es ribir un programa que invierta el ontenido de la memoria en bytes. Es de ir, si se tienen n bytes, el byte
de memoria n se invierte on el byte 0, el byte n-1 se inter ambia on el byte 1, et .

Cap
tulo 18

A eso de Ar hivos y llamadas al sistema


de dire torios
Existen mu has utileras que permiten manipular dire torios y ar hivos. Los omandos d, ls, rm, p, mkdir, et .
son ejemplos que han sido revisados ya en el sistema operativo.
Se revisara en este aptulo omo ha er las mismas tareas dentro de un programa en C.

18.1. Fun iones para el manejo de dire torios <unistd.h>


Para realizarlo se requiere llamar las fun iones apropiadas para re orrer la jerarqua de dire torios o preguntar
sobre los ontenidos de los dire torios.
int hdir( har *path) | ambia al dire torio indi ado en la adena path.
har *get wd( har *path, size t tam) | Obtiene la traye toria ompleta, es de ir, desde la raz del
dire torio a tual.path es un apuntador a una adena donde la traye toria sera regresada. La fun ion

devuelve un apuntador a la adena o NULL si un error o urre.


Se tiene a ontinua ion la emula ion del omando d de Unix on C:
#in lude <stdio.h>
#in lude <unistd.h>
#define TAM 80
main(int arg , har **argv)
{
har adena[TAM;
if (arg < 2)
{
printf("Uso: %s <dire torio> \n",argv[0);
exit(1);
}
if ( hdir(argv[1) != 0)
{

103

CAPITULO 18. ACCESO DE ARCHIVOS Y LLAMADAS AL SISTEMA DE DIRECTORIOS

104

printf("Error en %s.\n",argv[0);
exit(1);
}
get wd( adena,TAM);
printf("El dire torio a tual es %s\n", adena);

18.1.1. Busqueda y ordenamiento de dire torios: sys/types.h,sys/dir.h


Dos fun iones utiles (en plataformas BSD y apli a iones no multi-thread ) estan disponibles:
int s andir( onst har *dir, stru t dirent **listanomb,
int (*sele t)( onst stru t dirent *),
int (* ompar)( onst stru t dirent **, onst stru t dirent **)

Esta fun ion rastrea el dire torio dir, llamando sele t() en ada entrada de dire torio. Las entradas para las que
sele t() devuelve un valor distinto de ero se alma enan en adenas que se asignan de la memoria on mallo (),
ordenadas usando qsort() on la fun ion de ompara ion ompar(), y puestas en la matriz listanomb. Si sele t
es NULL, se sele ionan todas las entradas.
int alphasort( onst stru t dirent **a, onst stru t dirent **b);

Puede ser usada omo fun ion de ompara ion para que la fun ion s andir() ponga las entradas de dire torio
en orden alfabeti o.
A ontinua ion se tiene una version simple del omando de UNIX ls
#in lude
#in lude
#in lude
#in lude

<dirent.h>
<unistd.h>
<sys/param.h>
<stdio.h>

#define FALSO 0
#define VERDADERO !FALSO
extern int alphasort();
har traye toria[MAXPATHLEN;
main()
{
int ontar,i;
stru t dirent **ar hivos;
int sele _ar h();
if ( getwd(traye toria) == NULL )

CAPITULO 18. ACCESO DE ARCHIVOS Y LLAMADAS AL SISTEMA DE DIRECTORIOS

105

{
printf("Error obteniendo la traye toria a tual\n");
exit(0);
}
printf("Dire torio de trabajo a tual: %s\n",traye toria);
ontar = s andir(traye toria, &ar hivos, sele _ar h, alphasort);
/* Si no se en ontraron ar hivos */
if ( ontar <= 0)
{
printf("No hay ar hivos en este direntorio\n");
exit(0);
}
printf("Hay %d ar hivos.\n", ontar);
for (i=1;i< ontar+1;++i)
printf("%s ",ar hivos[i-1->d_name);
printf("\n"); /* flush buffer */
}
int sele _ar h(stru t dirent *entry)
{
if ((str mp(entry->d_name, ".") == 0) ||
(str mp(entry->d_name, "..") == 0))
return (FALSO);
else
return (VERDADERO);
}
s andir regresa los pseudodire torios (.), (..) y tambien todos los ar hivos. En este ejemplo se ltran los
pseudodire torios para que no se muestren ha iendo que la fun ion regrese FALSO.
Los prototipos de las fun iones s andir y alphasort tienen de ni iones en la abe era dirent.h
MAXPATHLEN esta de nida en sys/param.h y la fun ion getwd() en unistd.h.

Se puede ir mas lejos que lo anterior y bus ar por ar hivos parti ulares.
Rees ribiendo la fun ion sele _ar h para que solo muestre los ar hivos on los su jos . , .h y .o.
int sele _ar h(stru t dirent *entry)
{
har *ptr;
if ((str mp(entry->d_name, ".")== 0) ||
(str mp(entry->d_name, "..") == 0))
return (FALSO);
/* Revisar las extensiones de los ar hivos */
ptr = rindex(entry->d_name, '.'); /* Probar que tenga un punto */
if ( (ptr != NULL ) &&
( (str mp(ptr, ". ") == 0)

CAPITULO 18. ACCESO DE ARCHIVOS Y LLAMADAS AL SISTEMA DE DIRECTORIOS

106

|| (str mp(ptr, ".h") == 0)


|| (str mp(ptr, ".o") == 0) )
)
return (VERDADERO);
else
return(FALSO);
}

La fun ion rindex() es una fun ion para manejo de adenas que regresa un apuntador a la ultima o urren ia del
ara ter en la adena s, o un apuntador NULL si no o urre en la adena. (index() es una fun ion similar pero
asigna un apuntador a la primera o urren ia.)

18.2. Rutinas de manipula ion de ar hivos: unistd.h, sys/types.h, sys/stat.h


Existen varias llamadas al sistema que pueden ser apli adas dire tamente a los ar hivos guardados en un dire torio.

18.2.1. Permisos de a esos a ar hivos


La fun ion int a ess( onst har *traye toria, int modo); | determina los permisos de usuario para un
hero, de a uero on modo, que esta de nido en #in lude <unistd.h>, los uales pueden ser:
R OK {prueba el permiso de le tura.
W OK {prueba el permiso de es ritura.
X OK {prueba el permiso de eje u ion o busqueda.
F OK {prueba si se permite la omproba ion de la existen ia del hero.

La fun ion a ess() regresa: 0 si ha habido exito, o -1 en aso de falla y a errno se le asigna un valor ade uado.
Ver las paginas del man para ver la lista de errores.

errno
Algunas llamadas al sistema (y algunas fun iones de bibliote a) dan un valor al entero errno para indi ar que
ha habido un error. Esta es una variable espe ial del sistema.
Para usar errno en un programa de C, debe ser de larado de la siguiente forma:
extern int errno;

Esta puede ser manualmente puesto dentro de un programa en C, de otra forma simplemente retiene el ultimo
valor.
La fun ion int hmod( onst har *traye toria, mode_t modo); ambia el modo del ar hivo dado mediante
traye toria para un modo dado.
hmod() devuelve 0 en aso de exito y -1 en aso de error ademas se asigna a la variable errno un valor ade uado
(revisar las paginas de man para ver los tipos de errores)

18.2.2. Estado de un ar hivo


Se tienen dos fun iones utiles para ono er el estado a tual de un ar hivo. Por ejemplo se puede sabe que tan
grande es un ar hivo (st size), uando fue reado (st time), et (ver la de ni ion de la estru tura abajo). Las dos
fun iones tienen sus prototipos en <sys/stat.h>

CAPITULO 18. ACCESO DE ARCHIVOS Y LLAMADAS AL SISTEMA DE DIRECTORIOS

107

int stat( onst har *nomb ar h, stru t stat *buf) | obtiene informa ion a er a del ar hivo apuntado
por nomb_ar h. No se requieren permisos de le tura, es ritura o eje u ion, pero todos los dire torios
listados en nomb_ar h deberan estar disponibles.
int fstat(int desar h, stru t stat *buf) | obtiene la misma informa ion que el anterior, pero solo el
ar hivo abierto apuntado por desar h (tal y omo lo devuelve open()) es examinado en lugar de
nomb_ar h.

Las fun iones stat() y fstat() regresan 0 en aso exito, -1 si hubo error y errno es a tualizado apropiadamente.
buf es un apuntador a la estru tura stat en la ual la informa ion es olo ada. La estru tura stat esta de nida
en in lude <sys/stat.h>, omo sigue:
stru t stat
{
dev_t
ino_t
mode_t
nlink_t
uid_t
gid_t
dev_t

st_dev;
st_ino;
st_mode;
st_nlink;
st_uid;
st_gid;
st_rdev;

/*
/*
/*
/*
/*
/*
/*

off_t
st_size;
/*
unsigned long st_blksize; /*
unsigned long st_blo ks;
time_t
st_atime;
time_t
st_mtime;
time_t
st_ time;

/*
/*
/*
/*

dispositivo */
inodo */
prote ion */
numero de enla es fisi os */
ID del usuario propietario */
ID del grupo propietario */
tipo dispositivo (si es
dispositivo inodo) */
tama~no total, en bytes */
tama~no de bloque para el
sistema de fi heros de E/S */
numero de bloques asignados */
hora ultimo a eso */
hora ultima modifi a ion */
hora ultimo ambio */

};

Se muestra un ejemplo que ha e uso de la fun ion stat:


#in lude <stdio.h>
#in lude <sys/stat.h> /* Para la estru tura stat */
#in lude <unistd.h>
main(int arg , har **argv)
{
stru t stat buf;
printf("%s\n",argv[0);
if ( stat(argv[0, &buf) == -1 )
{
perror(argv[0);
exit(-1);
}
else

CAPITULO 18. ACCESO DE ARCHIVOS Y LLAMADAS AL SISTEMA DE DIRECTORIOS

108

{
printf("Tama~no del ar hivo %s %d bytes.\n",argv[0,buf.st_size);
}
}

18.2.3. Manipula ion de ar hivos: stdio.h, unistd.h


Existen algunas fun iones para borrar y renombrar ar hivos. Quizas la forma mas omun es usando las fun iones
de stdio.h:
int remove( onst har *pathname);
int rename( onst har *viejo, onst har *nuevo);

Dos llamadas al sistema (de nidas en unistd.h) las uales son a tualmente usadas por las fun iones remove()
y rename() tambien existen, pero son probablemente mas d iles de re ordar, al menos que se este su ientemente
familiarizado on UNIX.
int unlink( onst har *pathname); | borra un nombre del sistema de ar hivos. Si di ho nombre era

el ultimo enla e a un ar hivo, y ningun pro eso tiene el ar hivo abierto, el hero es borrado y el
espa io que o upaba vuelve a estar disponible. Regresa 0 en aso de exito, -1 en aso de error y pone
un valor en errno para indi arlo.

int link( onst har *oldpath, onst har *newpath); | rea un nuevo enla e (tambien ono ido omo

enla e fsi o a un ar hivo existente.

Las fun iones stat() y fstat() regresan 0 en aso exito, -1 si hubo error y pone la variable errno on algun
valor indi ando el tipo de error.

18.2.4. Crea ion de ar hivos temporales: <stdio.h>


Los programas on fre uen ia ne esitan rear ar hivos solo durante la vida de un programa. Existen dos fun iones
onvenientes (ademas de algunas variantes) para la realiza ion de la tarea men ionada. El manejo (borrado de
ar hivos, et .) es tomado on uidado por el sistema operativo.
La fun ion FILE *tmpfile (void); rea un ar hivo temporal (en modo de le tura/es ritura binaria) y abre el
orrespondiente ujo. El ar hivo se borrara automati amente uando el programa termine.
La fun ion har *tmpnam( har *s); rea un nombre uni o para un ar hivo temporal usando el pre jo de traye tora P_tmpdir de nido en <stdio.h>.

18.3. Ejer i ios


1. Es ribir un programa en C para simular el omando ls -l de UNIX que muestre todos los ar hivos del dire torio
a tual, sus permisos, tama~no, et .
2. Es ribir un programa para mostrar las lneas de un ar hivo que ontenga una palabra dada omo argumento
al programa, es de ir, una version sen illa de la utilidad grep de UNIX.
3. Esribir un programa para mostrar una lista de ar hivos dados omo argumentos, parando ada 20 lneas hasta
que una te la sea presionada (una version simple de la utilera more de UNIX).
4. Es ribir un programa que liste todos los ar hivos del dire torio a tual y todos los ar hivos en los subse uentes
dire torios.

Cap
tulo 19

Fun iones para el tiempo


En este aptulo se revisara omo se puede usar el reloj on llamadas al sistema UNIX.
Existen mu has fun iones para el tiempo que las que seran onsideradas aqu | usar las paginas de man y los
listados de la bibliote a estandar de fun iones para mas detalles.
El uso mas omun de las fun iones de tiempo son:
ono er el tiempo,
tomar el tiempo a programas y fun iones y
poner valores a semillas.

19.1. Fun iones basi as para el tiempo


Algunas prototipos de las fun iones basi as para el tiempo son las siguientes:
time t time(time t *t) | devuelve el tiempo trans urrido, medido en segundos desde \la epo a" 0

horas, 0 minutos, 0 segundos, tiempo universal oordinado (GMT) del 1o de enero de 1970. Esta
medida se llama el \tiempo de alendario". Si t no es nulo, el valor devuelto tambien se guarda en
la zona de memoria a la que apunta t. En aso de error, se devuelve ((time_t)-1) y se asigna a la
variable errno un valor apropiado.

ftime(stru t timeb *pt) | devuelve la hora y la fe ha a tuales en pt, que esta de larada en <sys/timeb.h>

omo sigue:

stru t timeb
{
time_t time;
unsigned short int millitm;
short int timezone;
short int dstflag;
};

/*
/*
/*
/*

Segundos desde epo a, igual que `time'.


*/
millisegundos adi ionales.
*/
Tiempo lo al medido en minutos oeste de GMT.*/
No ero si se usa horario de verano
*/

En aso de exito, se devuelve el tiempo trans urrido en segundos desde la epo a. En aso de error,
se devuelve ((time_t)-1) y se asigna a la variable errno un valor apropiado.
har * time(time t *timep) | toma un argumento de tipo time_t (long integer) que representa el
tiempo de alendadrio y lo onvierte a una adena de 26 ara teres de la forma produ ida por
la fun ion as time(). En primer lugar des ompone los segundos a una estru tura tm llamando a
lo altime(), y enton es llama a as time() para onvertir la estru tura tm a una adena.

109

CAPITULO 19. FUNCIONES PARA EL TIEMPO

110

har *as time( onst stru t tm *timeptr) | onvierte un valor de tiempo ontenido en una estru tura
tm a una adena de 26 ara teres de la forma:

ddd mmm dd hh:mm:ss aaaa

La fun ion as time() regresa un apuntador a la adena.

19.2. Ejemplos de apli a iones de fun iones del tiempo.


Como se men iono previamente, basi amente existen tres posibles usos de las fun iones de tiempo.

19.2.1. Ejemplo 1: Tiempo (en segundos) para ha er algun al ulo.


Este es un ejemplo sen illo que ilustra las llamadas a la fun ion tiempo en distintos momentos:
/* timer. */
#in lude <stdio.h>
#in lude <sys/types.h>
#in lude <time.h>
main()
{
int i,j;
time_t t1,t2;
(void) time(&t1);
for (i=1; i<=300; ++i)
{
printf("%d %d %d\n",i, i*i, i*i*i );
for(j=0; j<1000000; j++); /* Un peque~no retardo */
}
(void) time(&t2);
printf("\n Tiempo para ha er 300 uadrados y ubos = %d segundos\n",
(int) t2-t1);
}

19.2.2. Ejemplo 2: Ini ializar la semilla de un numero aleatorio.


Se ha visto un ejemplo similar previamente, en esta o asion se usa la fun ion lrand48() para generar una
se uen ia de numeros:
/* random. */
#in lude <stdio.h>
#in lude <sys/types.h>
#in lude <time.h>
main()
{
int i;

CAPITULO 19. FUNCIONES PARA EL TIEMPO

111

time_t t1;
(void) time(&t1);
srand48((long) t1);
/* usar time en segundos para poner la semilla */
printf("5 numeros aleatorios (semilla = %d):\n",(int) t1);
for (i=0;i<5;++i)
printf("%d ", lrand48());
printf("\n\n");
}

La fun ion lrand48() devuelve enteros largos no negativos distribuidos uniformememnte entre 0 y 231 .
Una fun ion similar es la fun ion drand48 que regresa numeros de doble pre ision en el rango [0;0; 1;0).
srand48() pone el valor de la semilla para estos generadores de n
umeros aleatorios. Es importante tener diferentes
semillas uando se llame a las fun iones de otra forma el mismo onjunto numeros pseudo-aleatorios sera generados.
La fun ion time() siempre da una semilla uni a (siempre y uando haya trans urrido por lo menos 1 segundo).

19.3. Ejer i ios


1. Es ribir un programa en C que mida el tiempo de un fragmento de odigo en milisegundos.
2. Es ribir un programa en C para produ ir una serie de numeros aleatorios de punto otante en los rangos a)
0.0 - 1.0, b) 0.0 - n, donde n es ualquier valor otante. La semilla debera estar puesta para que se garanti e
una se uen ia uni a.

Cap
tulo 20

Control de pro esos: <stdlib.h>,


<unistd.h>
Un pro eso es basi amente un uni o programa eje utandose. Este podra ser un programa del "sistema(por
ejemplo, login, sh, update, et ). un programa ini iado por el usuario (gimp o alguno he ho por el usuario).
Cuando UNIX eje uta un pro eso le asigna a ad pro eso un numero uni o | pro ess ID o pid.
El omando ps de UNIX lista todos los pro esos que se estan eje utando en la maquina, listando tambien el pid.
La fun ion de C int getpid() regresara el pid de un pro eso que llame a esta fun ion.
Un programa usualmente eje uta un solo pro eso. Sin embargo despues se vera omo se puede ha er que un
programa orra omo varios pro esos separados omuni ados.

20.1. Eje utando omandos de UNIX desde C


Se pueden eje utar omandos desde un programa de C omo si se estuviera en la lnea de omandos de UNIX
usando la fun ion system(). NOTA: se puede ahorrar bastante tiempo y onfusion en vez de eje utar otros programas,
s ripts, et . para ha er las tareas.
int system( har *mandato) | donde mandato puede ser el nombre de una utilera de UNIX, un shell eje utable
o un programa del usuario. La fun ion regresa el status de salida del shell. La fun ion tiene su prototipo en <stdlib.h>
Ejemplo: llamada del omando ls desde un programa
main()
{
printf("Ar hivos en el dire torio son:\n");
system("ls -l");
}

La fun ion system es una llamada que esta onstruida de otras 3 llamadas del sistema: exe l(), wait() y fork()
(las uales tienen su prototipo en <unistd.h>).

20.2. exe l()


La fun ion exe l tiene otras 5 fun iones rela ionadas | ver las paginas de man.
La fun ion exe l realiza la eje u ion (exe ute ) y sale (leave ), es de ir que un pro eso sera eje utado y enton es
terminado por exe l.
Esta de nida omo:
112

CAPITULO 20. CONTROL DE PROCESOS: <STDLIB.H>, <UNISTD.H>

113

exe l ( onst har * amino, onst har *arg0, ..., har *argn, 0);

El ultimo parametro debera ser siempre 0. Este es un terminador Nulo. Como la lista de argumentos sea variable
se debe indi ar de alguna forma a C uando se termine la lista. El terminador nulo ha e lo anterior.
El apuntador amino indi a el nombre de un ar hivo que ontiene el omando que sera eje utado, arg0 apunta
a una adena que es el mismo nombre (o al menos su ultimo omponente).
arg1, ... , argn son apuntadores a los argumentos para el omando y el 0 solamente indi a el n de la lista
de argumentos variables.
Por lo tanto nuestro ejemplo queda de la siguiente forma:
#in lude <unistd.h>
main()
{
printf("Los ar hivos en el dire torio son:\n");
exe l("/bin/ls","ls","-l",0);
printf("<<< Esto no se eje uta !!!\n");
}

20.3. fork()
La fun ion int fork() ambia un pro eso uni o en 2 pro esos identi os, ono idos omo el padre (parent) y el
hijo ( hild). En aso de exito, fork() regresa 0 al pro eso hijo y regresa el identi ador del pro eso hijo al pro eso
padre. En aso de falla, fork() regresa 1 al pro eso padre, pone un valor a errno, y no se rea un pro eso hijo.
El pro eso hijo tendra su propio identi ador uni o (PID).
El siguiente programa ilustra un ejemplo sen illo del uso de fork, donde dos opias son he has y se eje utan
juntas (multitarea).
main()
{
int valor_regr=0;
printf("Bifur ando el pro eso\n");
valor_regr=fork();
printf("El id del pro eso es %d y el valor regresado es %d\n",
getpid(), valor_regr);
exe l("/bin/ls","ls","-l",0);
printf("Esta linea no es impresa\n");
}

La salida podra ser omo la siguiente:


Bifur ando el pro eso
El id del pro eso es 2662 y el valor regresado es 2663
El id del pro eso es 2663 y el valor regresado es 0

Los pro esos tienen un uni o identi ador, el ual sera diferente en ada eje u ion.

CAPITULO 20. CONTROL DE PROCESOS: <STDLIB.H>, <UNISTD.H>

114

Es imposible indi ar on antela ion ual pro eso obtendra el CPU. Cuando un pro eso es dupli ado en 2 pro esos
se puede dete tar fa ilmente (en ada pro eso) si el pro eso es el hijo o el padre ya que fork() regresa 0 para el hijo.
Se pueden atrapar ualquier error, ya que fork() regresa un 1, por ejemplo:
int pid; /* identifi ador del pro eso */
pid = fork();
if ( pid < 0 )
{
printf("<< No se pudo dupli ar !!\n");
exit(1);
}
if ( pid == 0 )
{
/* Pro eso hijo */
......
}
else
{
/* Pro eso padre */
......
}

20.4. wait()
La fun ion int wait() (int *status) forzara a un pro eso padre para que espere a un pro eso hijo que se
detenga o termine. La fun ion regresa el PID del hijo o 1 en aso de errror. El estado de la salida del hijo es
regresado en status.

20.5. exit()
La fun ion void exit(int status) termina el pro eso que llama a esta fun ion y regresa en la salida el valor
de status. Tanto UNIX y los programas bifur ados de C pueden leer el valor de status.
Por onven ion, un estado de 0 signi a termina ion normal y ualquier otro indi a un error o un evento no
usual. Mu has llamadas de la bibliote a estandar tienen errores de nidos en la abe era de ar hivo sys/stat.h. Se
puede fa ilmente derivar su propia onven ion.
Un ejemplo ompleto de un programa de bifur a ion se muestra a ontinua ion:
/*
fork. - ejemplo de un programa de bifur a ion
El programa pide el ingreso de omandos de UNIX que son dejados en una
adena. La adena es enton es "analizada" en ontrando blan os, et
Cada omando y sus orrespondientes argumentos son puestos en
un arreglo de argumentos, exe vp es llamada para eje utar estos omandos
en un pro eso hijo generado por fork()

CAPITULO 20. CONTROL DE PROCESOS: <STDLIB.H>, <UNISTD.H>

*/
#in lude <stdio.h>
#in lude <sys/types.h>
#in lude <unistd.h>
main()
{
har buf[1024;
har *args[64;
for (;;)
{
/*
* Pide y lee un omando.
*/
printf("Comando: ");
if (gets(buf) == NULL)
{
printf("\n");
exit(0);
}
/*
* Dividir la adena en argumentos.
*/
parse(buf, args);
/*
* Eje utar el omando.
*/
eje utar(args);
}
}
/*
* parse--divide el omando que esta en buf
*
en argumentos.
*/
parse( har *buf, har **args)
{
while (*buf != ( har) NULL)
{
/*
* Quitar blan os. Usar nulos, para que
* el argumento previo sea terminado

115

CAPITULO 20. CONTROL DE PROCESOS: <STDLIB.H>, <UNISTD.H>

* automati amente.
*/
while ( (*buf == ' ') || (*buf == '\t') )
*buf++ = ( har) NULL;
/*
* Guardar los argumentos
*/
*args++ = buf;
/*
* Brin ar sobre los argumentos.
*/
while ((*buf != ( har) NULL) && (*buf != ' ') && (*buf != '\t'))
buf++;
}
*args = ( har) NULL;
}

/*
* eje utar--genera un pro eso hijo y eje uta
*
el programa.
*/
eje utar( har **args)
{
int pid, status;
/*
* Obtener un pro eso hijo.
*/
if ( (pid = fork()) < 0 )
{
perror("fork");
exit(1);
/* NOTA: perror() genera un mensaje de error breve en la
* salida de errores des ribiendo el ultimo error en ontrado
* durante una llamada al sistema o fun ion de la bibliote a.
*/
}
/*
* El pro eso hijo eje uta el odigo dentro del if.
*/
if (pid == 0)

116

CAPITULO 20. CONTROL DE PROCESOS: <STDLIB.H>, <UNISTD.H>

117

{
exe vp(*args, args);
perror(*args);
exit(1);
/* NOTA: las versiones exe v() y exe vp() de exe l() son utiles uando
el numero de argumentos es des ono ido previamente.
Los argumentos para exe v() y exe vp() son el nombre del ar hivo que
sera eje utado y un ve tor de adenas que ontienen los argumentos.
El ultimo argumento de adema debera ser un apuntador a 0 (NULL)
exe lp() y exe vp() son llamados on los mismos argumentos que
exe l() y exe v(), pero dupli an las a iones del shell en
la busqueda de un ar hivo eje utable en un lista de dire torios.
La lista de dire torios es obtenida del ambiente.
*/
}
/*
* El padre eje uta el wait.
*/
while (wait(&status) != pid)
/* va io */ ;
}

20.6. Ejer i ios


1. Crear un programa en C en donde se use la fun ion popen() para entubar la salida del omando rwho de UNIX
en el omando more de UNIX.

Cap
tulo 21

Compila i
on de Programas on Ar hivos
M
ultiples
En este aptulo se revisa los aspe tos teori os y pra ti os que ne esitan ser onsiderados uando son es ritos
programas grandes.
Cuando se es riben programas grandes se debera programar en modulos. Estos seran ar hivos fuentes separados.
La fun ion main() debera estar en un ar hivo, por ejemplo en main. , y los otros ar hivos tendran otras fun iones.
Se puede rear una bibliote a propia de fun iones es ribiendo una suite de subrutinas en uno o mas modulos. De
he ho los modulos pueden ser ompartidos entre mu hos programas simplemente in luyendo los modulos al ompilar
omo se vera a ontinua ion.
Se tiene varias ventajas si los programas son es ritos de esta forma:
los modulos de forma natural se dividiran en grupos omunes de fun iones.
se puede ompilar ada modulos separadamente y ligarlo on los modulos ya ompilados.
las utileras tales omo make nos ayudan a mantener sistemas grandes.

21.1. Ar hivos Cabezera


Si se adopta el modelo modular enton es se querra tener para ada modulo las de ni iones de las variables, los
prototipos de las fun iones, et . Sin embargo, >que su ede si varios modulos ne esitan ompartir tales de ni iones?
En tal aso, lo mejor es entralizar las de ni iones en un ar hivo, y ompartir el ar hivo entre los modulos. Tal
ar hivo es usualmente llamado un ar hivo abe era.
Por onven ion estos ar hivos tienen el su jo .h
Se han revisado ya algunos ar hivos abe era de la bibliote a estandar, por ejemplo:
#in lude <stdio.h>

Se pueden de nir los propios ar hivos abe era y se pueden in luir en el programa omo se muestra enseguida:
#in lude "mi_ abe era.h"

Los ar hivos abe era por lo general solo ontienen de ni iones de tipos de datos, prototipos de fun iones y
omandos del prepro esador de C.
Considerar el siguiente programa de ejemplo:
main.
118

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

/*
*
main.
*/
#in lude " abe era.h"
#in lude <stdio.h>
har

*Otra_ adena = "Hola a Todos";

main()
{
printf("Eje utando...\n");
/*
*
Llamar a Es ribirMiCadena() - definida en otro ar hivo
*/
Es ribirMiCadena(MI_CADENA);
printf("Terminado.\n");
}

Es ribirMiCadena.
/*
*
Es ribirMiCadena.
*/
extern har
*Otra_ adena;
void Es ribirMiCadena(EstaCadena)
har
*EstaCadena;
{
printf("%s\n", EstaCadena);
printf("Variable Global = %s\n", Otra_ adena);
}

abe era.h
/*
*
abe era.h
*/
#define MI_CADENA "Hola Mundo"
void Es ribirMiCadena();

Cada modulo sera ompilado separadamente omo se vera mas adelante.

119

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

120

Algunos modulos tienen la dire tiva de prepro esamiento #in lude " abe era.h" ya que omparten de ni iones
omunes. Algunos omo main. tambien in luyen ar hivos abe era estandar. La fun ion main. llama a la fun ion
Es ribirMiCadena() la ual esta en el modulo (ar hivo) Es ribirMiCadena.
El prototipo void de la fun ion Es ribirMiCadena esta de nida en abe era.h.
Observar que en general se debe de idir entre tener un modulo . que tenga a eso solamente a la informa ion que
ne esita para su trabajo, on la onse uen ia de mantener mu hos ar hivos abe era y tener programas de tama~no
moderado on uno o dos ar hivos abe era (probablemente lo mejor) que ompartan mas de ni iones de modulos.
Un problema que se tiene al emplear modulos son el ompartir variables. Si se tienen variables globales de laradas
y son instan iadas en un modulo, > omo pueden ser pasadas a otros modulos para que sean ono idas?
Se podran pasar los valores omo parametros a las fun iones, pero:
puede ser esto laborioso si se pasan los mismos parametros a mu has fun iones o si la lista de argumentos es
muy larga.
arreglos y estru turas muy grandes son dif iles de guardar lo almente | problemas de memoria on el sta k.

21.2. Variables y Fun iones Externas


Las variables y argumentos de nidos dentro de las fun iones son \internas", es de ir, lo ales.
Las variables \externas" estan de nidas fuera de las fun iones | se en uentran poten ialmente disponibles a todo
el programa (globales) pero NO ne esariamente. Las variables externas son siempre permanentes.
En el lenguaje C, todas las de ni iones de fun iones son externas, NO se pueden tener de lara iones de fun iones
anidadas omo en PASCAL.

21.2.1. Al an e de las variables externas


Una variable externa (o fun ion) no es siempre totalmente global. En el lenguaje C se apli a la siguiente regla:
El al an e de una variable externa (o fun ion) ini ia en el punto de de lara ion hasta el n del ar hivo (modulo)
donde fue de larada.
Considerar el siguiente odigo:
main()
{ ... }
int que_al an e;
float fin_de_al an e[10;
void que_global()
{ ... }
har solitaria;
float fn()
{ ... }

La fun ion main() no puede ver a las variables que_al an e o fin_de_al an e, pero las fun iones que_global()
y fn() si pueden. Solamente la fun ion fn() puede ver a solitaria.
Esta es tambien una de las razones por las que se deben poner los prototipos de las fun iones antes del uerpo
del odigo.

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

121

Por lo que en el ejemplo la fun ion main no ono era nada a er a de las fun iones que_global() y fn(). La
fun ion que_global() no sabe nada a er a de la fun ion fn(), pero fn() si sabe a er a de la fun ion que_global(),
ya que esta apare e de larada previamente.
La otra razon por la ual se usan los prototipos de las fun iones es para revisar los parametros que seran pasados
a las fun iones.
Si se requiere ha er referen ia a una variable externa antes de que sea de larada o que esta de nida en otro
modulo, la variable debe ser de larada omo una variable externa, por ejemplo:
extern int que_global;

Regresando al ejemplo de programa ion modular, se tiene una arreglo de ara teres tipo global Otra_ adena
de larado en main. y que esta ompartido on Es ribirMiCadena donde esta de larada omo externa.
Se debe tener uidado on el espe i ador de alma enamiento de lase ya que el pre jo es una de lara ion, NO
una de ni ion, esto es, no se da alma enamiento en la memoria para una variable externa | solamente le di e al
ompilador la propiedad de la variable. La variable a tual solo debera estar de nida una vez en todo el programa |
se pueden tener tantas de lara iones externas omo se requieran.
Los tama~nos de los arreglos deberan ser dados dentro de la de lara ion, pero no son ne esarios en las de lara iones
externas, por ejemplo:
main.

int arr[100;

ar h.

extern int arr[;

21.3. Ventajas de Usar Varios Ar hivos


Las ventajas prin ipales de dispersar un programa en varios ar hivos son:
Equipos de programadores pueden trabajar en el programa, ada programador trabaja en un ar hivo diferente.
Puede ser usado un estilo orientado a objetos. Cada ar hivo de ne un tipo parti ular de objeto omo un tipo de
dato y las opera iones en ese objeto omo fun iones. La implementa ion del objeto puede mantenerse privado al
resto del programa. Con lo anterior se logran programas bien estru turados los uales son fa iles de mantener.
Los ar hivos pueden ontener todas las fun iones de un grupo rela ionado, por ejemplo todas las opera iones
on matri es. Estas pueden ser a esadas omo una fun ion de una bibliote a.
Objetos bien implementados o de ni iones de fun iones pueden ser reusadas en otros programas, on lo que se
redu e el tiempo de desarrollo.
En programas muy grandes ada fun ion prin ipal puede o upar un propio ar hivo. Cualquier otra fun ion de
bajo nivel usada en la implemanta ion puede ser guardada en el mismo ar hivo, por lo que los programadores
que llamen a la fun ion prin ipal no se distraeran por el trabajo de bajo nivel.
Cuando los ambios son he hos a un ar hivo, solamente ese ar hivo ne esita ser re ompilado para re onstruir
el programa. La utilera make de UNIX es muy util para re onstruir programas on varios ar hivos.

21.4. Como dividir un programa en varios ar hivos


Cuando un programa es separado en varios ar hivos, ada ar hivo ontendra una o mas fun iones. Un ar hivo
in luira la fun ion main() mientras los otros ontendran fun iones que seran llamados por otros. Estos otros ar hivos
pueden ser tratados omo fun iones de una bibliote a.

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

122

Los programadores usualmente ini ian dise~nando un programa dividiendo el problema en se iones mas fa ilmente
manejables. Cada una de estas se iones podran ser implementaddas omo una o mas fun iones. Todas las fun iones
de ada se ion por lo general estaran en un solo ar hivo.
Cuando se ha e una implementa ion tipo objeto de las estru turas de datos, es usual tener todas las fun iones
que a esan ese objeto en el mismo ar hivo. Las ventajas de lo anterior son:
El objeto puede ser fa ilmente reusado en otros programas.
Todas las fun iones rela ionadas estan guardadas juntas.
Los ultimos ambios al objeto requieren solamente la modi a ion de un ar hivo.
El ar hivo ontiene la de ni ion de un objeto, o fun iones que regresasan valores, hay una restri ion en la llamada
de estas fun iones desde otro ar hivo, al menos que la de ni ion de las fun iones esten en el ar hivo, no sera posible
ompilar orre tamente.
La mejor solu ion a este problema es es ribir un ar hivo abe era para ada ar hivo de C, estos tendran el mismo
nombre que el ar hivo de C, pero terminaran en .h. El ar hivo abe era ontiene las de ni iones de todas las fun iones
usadas en el ar hivo de C.
Cuando una fun ion en otro ar hivo llame una fun ion de nuestro ar hivo de C, se puede de nir la fun ion usando
la dire tiva #in lude on el ar hivo apropiado .h

21.5. Organiza ion de los Datos en ada Ar hivo


Cualquier ar hivo debera tener sus datos organizados en un ierto orden, tip amente podra ser la siguiente:
Un preambulo onsistente de las de ni iones de onstantes (#define), abe eras de ar hivos (#in lude) y los
tipos de datos importantes (typedef).
De lara ion de variables globales y externas. Las variables globales podran estar ini ializadas aqu.
Una o mas fun iones.
El orden anterior es importante ya que ada objeto debera estar de nido antes de que pueda ser usado. Las
fun iones que regresan valores deberan estar de nidos antes de que sean llamados. Esta de ni ion podra ser una de
las siguientes:
El lugar en que la fun ion esta de nida y llamada en el mismo ar hivo, una de lara ion ompleta de la fun ion
puede ser olo ada delante de ualquier llamada de la fun ion.
Si la fun ion es llamada desde un ar hivo donde no esta de nida, un prototipo debera apare er antes que
llamada de la fun ion.
Una fun ion de nida omo:
float en _max(float a, float b, float )
{ ... }

podra tener el siguiente prototipo:


float en _max(float a, float b, float );

El prototipo puede apare er entre las variables globales en el ini io del ar hivo fuente. Alternativamente puede
ser de larado en el ar hivo abe era el ual es ledo usando la dire tiva #in lude.
Es importante re ordar que todos los objetos en C deberan estar de larados antes de ser usados.

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

123

21.6. La utilera Make


La utilera Make es un manejador inteligente de programas que mantiene la integridad de una ole ion de modulos
de un programa, una ole ion de programas o un sistema ompleto | no tienen que ser programas, en la pra ti a
puede ser ualquier sistema de ar hivos (por ejemplo, aptulos de texto de un libro que esta siendo tipogra ado).
Su uso prin ipal ha sido en la asisten ia del desarrollo de sistemas de software.
Esta utilera fue ini ialmente desarrollada para UNIX, pero a tualmente esta disponible en mu hos sistemas.
Observar que make es una herramienta del programador, y no es parte del lenguaje C o de alguno otro.
Supongamos el siguiente problema de mantenimiento de una ole ion grande de ar hivos fuente:
main. f1. ...... fn.

Normalmente se ompilaran los ar hivos de la siguiente manera:


g -o main main. f1. ....... fn.

Sin embargo si se sabe que algunos ar hivos han sido ompilados previamente y sus ar hivos fuente no han sido
ambiados desde enton es, enton es se puede ahorrar tiempo de ompila ion ligando los odigos objetos de estos
ar hivos, es de ir:
g -o main main. f1. ... fi.o ... fj.o ... fn.

Se puede usar la op ion - del ompilador de C para rear un odigo objeto (.o) para un modulo dado. Por
ejemplo:
g - main.

que reara un ar hivo main.o. No se requiere propor ionar ninguna liga de alguna bibliote a ya que sera resuelta
en la etapa de ligamiento.
Se tiene el problema en la ompila ion del programa de ser muy larga, sin embargo:
Se onsume tiempo al ompilar un modulo . | si el modulo ha sido ompilado antes y no ha sido modi ado
el ar hivo fuente, por lo tanto no hay ne esidad de re ompilarlo. Se puede solamente ligar los ar hivos objeto.
Sin embargo, no sera fa il re ordar uales ar hivos han sido a tualizados, por lo que si ligamos un ar hivo
objeto no a tualizado, el programa eje utable nal estara in orre to.
Cuando se te lea una se uen ia larga de ompila ion en la lnea de omandos se ometen errores de te leo, o
bien, se te lea en forma in ompleta. Existiran varios de nuestros ar hivos que seran ligados al igual que ar hivos
de bibliote as del sistema. Puede ser dif il re ordar la se uen ia orre ta.
Si se usa la utilera make todo este ontrol es he ho on uidado. En general solo los modulos que sean mas viejos
que los ar hivos fuente seran re ompilados.

21.6.1. Programando Make


La programa ion de make es dire ta, basi amente se es ribe una se uen ia de omandos que des ribe omo nuestro
programa (o sistema de programas) sera onstrudo a partir de los ar hivos fuentes.
La se uen ia de onstru ion es des rita en los ar hivos makefile, los uales ontienen reglas de dependen ia y
reglas de onstru ion.
Una regla de dependen ia tiene dos partes | un lado izquierdo y un lado dere ho separados por :
lado izquierdo : lado dere ho

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

124

El lado izquierdo da el nombre del destino (los nombres del programa o ar hivos del sistema) que sera onstrudo
(target ), mientras el lado dere ho da los nombres de los ar hivos de los uales depende el destino (por ejemplo,
ar hivos fuente, ar hivos abe era, ar hivos de datos).
Si el destino esta fuera de fe ha on respe to a las partes que le onstituyen, las reglas de onstru ion siguiendo
las reglas de dependen ia son usadas.
Por lo tanto para un programa tpi o de C uando un ar hivo make es eje utado las siguientes tareas son he has:
1. El ar hivo make es ledo. El Makefile indi a uales objetos y ar hivos de bibliote a se requieren para ser ligados
y uales ar hivos abe era y fuente ne esitan ser ompilados para rear ada ar hivo objeto.
2. La hora y la fe ha de ada ar hivo objeto son revisados ontra el odigo fuente y los ar hivos abe era de los
uales dependen. Si ualquier fuente o ar hivo abe era son mas re ientes que el ar hivo objeto, enton es los
ar hivos han sido modi ados desde la ultima modi a ion y por lo tanto los ar hivos objeto ne esitan ser
re ompilados.
3. Una vez que todos los ar hivos objetos han sido revisados, el tiempo y la fe ha de todos los ar hivos objeto son
revisados ontra los ar hivos eje utables. Si existe ar hivos eje utables viejos seran re ompilados.
Observar que los ar hivos make pueden obede er ualquier omando que sea te leado en la lnea de omandos,
por onsiguiente se pueden usar los ar hivos make para no solamente ompilar ar hivos, sino tambien para ha er
respaldos, eje utar programas si los ar hivos de datos han sido ambiados o limpieza de dire torios.

21.7. Crea ion de un Ar hivo Make (Make le)


La rea ion del ar hivo es bastante simple, se rea un ar hivo de texto usando algun editor de textos. El ar hivo
Make le ontiene solamente una lista de dependen ias de ar hivos y omandos que son ne esarios para satisfa erlos.
Se muestra a ontinua ion un ejemplo de un ar hivo make:
prog: prog.o f1.o f2.o
g -o prog prog.o f1.o f2.o -lm ...
prog.o: abe era.h prog.
g - prog.
f1.o: abe era.h f1.
g - f1.
f2.o: ....
...

La utilera make lo interpretara de la siguiente forma:


1. prog depende de tres ar hivos: prog.o, f1.o y f2.o. Si ualquiera de los ar hivos objeto ha ambiado desde
la ultima ompila ion los ar hivos deben ser religados.
2. prog.o depende de 2 ar hivos, si estos han ambiado prog.o debera ser re ompilado. Lo mismo su ede on
f1.o y f2.o.
Los ultimos 3 omandos en makefile son llamados reglas expl itas | ya que los ar hivos en los omandos son
listados por nombre.
Se pueden usar reglas impl itas en makefile para generalizar reglas y ha er mas ompa ta la es ritura.
Si se tiene:

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

125

f1.o: f1.
g - f1.
f2.o: f2.
g - f2.

se puede generalizar a:
. .o: g - $<

Lo ual se lee omo .ext_fuente.ext_destino: omando donde $< es una forma breve para indi ar los ar hivos
que tienen la extension .
Se pueden insertar omentarios en un Makefile usando el smbolo #, en donde todos los ara teres que siguen a
# son ignorados.

21.8. Uso de ma ros on Make


Se pueden de nir ma ros para que sean usadas por make, las uales son tip amente usadas para guardar nombres
de ar hivos fuente, nombres de ar hivos objeto, op iones del ompilador o ligas de bibliote as.
Se de nen en una forma simple, por ejemplo:
FUENTES
CFLAGS
LIBS
PROGRAMA
OBJETOS

=
=
=
=
=

main. f1. f2.


-ggdb -C
-lm
main
(FUENTES: . = .o)

en donde (FUENTES: . = .o) ambia la extension . de los fuentes por la extension .o


Para referirse o usar una ma ro on make se debe ha er $(nomb_ma ro), por ejemplo:
$(PROGRAMA) : $(OBJETOS)
$(LINK.C) -o $ $(OBJETOS) $(LIBS)

En el ejemplo mostrado se observa que:


La lnea que ontiene $(PROGRAMA) : $(OBJETOS) genera una lista de dependen ias y el destino.
Se emplean ma ros internas omo $.
Existen varias ma ros internas a ontinua ion se muestran algunas de ellas:
$* Parte del nombre del ar hivo de la dependen ia a tual sin el su jo.
$ Nombre ompleto del destino a tual.
$ Ar hivo . del destino
Un ejemplo de un makefile para el programa modular dis utido previamente se muestra a ontinua ion:
#
# Makefile
#
FUENTES. =main. Es ribirMiCadena.

 DE PROGRAMAS CON ARCHIVOS MULTIPLES



CAPITULO 21. COMPILACION

126

INCLUDES=
CFLAGS=
SLIBS=
PROGRAMA=main
OBJETOS=$(FUENTES. :. =.o)
# Destino (target) espe ial (ini ia on .)
.KEEP_STATE:
debug := CFLAGS=-ggdb
all debug: $(PROGRAMA)
$(PROGRAMA): $(INCLUDES) $(OBJETOS)
$(LINK. ) -o $ $(OBJETOS) $(SLIBS)
lean:
rm -f $(PROGRAMA) $(OBJETOS)

Para ver mas informa ion de esta utilera dentro de Linux usar info make

21.9. Eje u ion de Make


Para usar make solamente se debera te lear en la lnea de omandos. El sistema operativo automati amente bus a
un ar hivo on el nombre Makefile (observar que la primera letra es mayus ula y el resto minus ulas), por lo tanto
si se tiene un ar hivo on el nombre Makefile y se te lea make en la lnea de omandos, el ar hivo Makefile del
dire torio a tual sera eje utado.
Se puede anular esta busqueda de este ar hivo te leando make -f makefile.
Existen algunas otras op iones para make las uales pueden ser onsultadas usando man.

Cap
tulo 22

Comuni a i
on entre pro esos (IPC
Interpro ess Communi ation), PIPES
A ontinua ion se ini iara la revision de omo multiples pro esos pueden estar siendo eje utados en una maquina
y quizas siendo ontrolados (generados por la fun ion fork()) por uno de nuestros programas.
En numerosas apli a iones hay una ne esidad lara para que estos pro esos se omuniquen para el inter ambio de
datos o informa ion de ontrol. Hay unos uantos metodos para ha er lo anterior. Se pueden onsiderar los siguientes:
Tubera (Pipes)
Se~nales (Signals)
Colas de Mensajes
Semaforos
Memoria Compartida
So kets
En este aptulo se estudia el entubamiento de dos pro esos, en los siguientes aptulos se revisan los otros
metodos.

22.1. Entubando en un programa de C <stdio.h>


El entubamiento es un pro eso donde la entrada de un pro eso es he ha on la salida de otro. Se ha visto ejemplos
de lo anterior en la lnea de omandos de Unix uando se usa el smbolo |.
Se vera omo ha er lo anterior en un programa de C teniendo dos (o mas) pro esos divididos. Lo primero que se
debe ha er es abrir una tubera, en Unix permite dos formas de ha erlo:

22.1.1. popen() Tubera formateada


FILE *popen( har *orden, har *tipo) Abre una tubera de E/S donde el omando es el pro eso que sera one tado al pro eso que lo esta llamando de esta forma reando el pipe. El tipo es "r{ para le tura, o "w"para le tura.
La fun ion popen() regresa un apuntador a un ujo o NULL para algun tipo de error.
Una tubera abierta on popen() debera siempre errarse on p lose(FILE *flujo).
Se usa fprintf() y fs anf() para omuni arse on el ujo de la tubera.

127

 ENTRE PROCESOS (IPC INTERPROCESS COMMUNICATION), PIPES128


CAPITULO 22. COMUNICACION

22.1.2. pipe() Tubera de bajo nivel


int pipe(int des f[2) Crea un par de des ritores de ar hivo, que apuntan a un nodo i de una tubera, y los
pone en el ve tor de dos elementos apuntado por des f. des f[0 es para le tura y des f[1 es para es ritura.
pipe() regresa 0 en aso de exito, y en aso de error se devuelve -1 y se pone un valor apropiado en errno.

El modelo de programa ion estandar es que una vez que la tubera ha sido puesta, dos (o mas) pro esos ooperativos seran reados por division y los datos seran pasados empleando read() y write().
Las tuberas abiertas on pipe() deberan ser erradas on lose(int fd). A ontinua ion se muestra un ejemplo
de entubamiento que se utiliza para estar enviando datos al programa gnuplot, empleado para gra ar. La des rip ion
de las fun iones de los modulos es la siguiente:
El programa tiene dos modulos, grafi a. que ontiene la fun ion main() y grafi ador. que
ontiene las rutinas para enviar los datos al programa gnuplot.
El programa supone que se tiene instalado el programa de gra a ion gnuplot en el dire torio
/usr/bin.
El programa grafi a. llama al programa gnuplot.
Dos ujos son generados usando el programa grafi a. , en uno de ellos se gra a la fun ion
y=0.5 e y=aleat(0-1.0) y en el otro las fun iones y=sen(x) e y=sen(1/x).
Dos tuberas son readas ada una on un ujo de datos.
Gnuplot genera en \vivo" la salida de las gra as.

El listado del odigo para grafi a. es el siguiente:


/* grafi a. * Ejemplo de la tuberias (pipe) de Unix. Se llama al paquete "gnuplot"
* para grafi ar desde un programa en C.
* La informa ion es entubada a gnuplot, se rean 2 tuberias, una dibujara la
* grafi a de y=0.5 e y= random 0-1.0, la otra grafi ara y=sen(1/x) e y=sen x
*/
#in lude "externals.h"
#in lude <signal.h>
#define DEG_TO_RAD(x) (x*180/M_PI)
void salir();
FILE *fp1, *fp2, *fp3, *fp4;
main()
{
float i;
float y1,y2,y3,y4;
/* abrir ar hivos en los uales se guardaran los datos a grafi ar */
if ( ((fp1 = fopen("plot11.dat","w")) == NULL) ||
((fp2 = fopen("plot12.dat","w")) == NULL) ||

 ENTRE PROCESOS (IPC INTERPROCESS COMMUNICATION), PIPES129


CAPITULO 22. COMUNICACION

((fp3 = fopen("plot21.dat","w")) == NULL) ||


((fp4 = fopen("plot22.dat","w")) == NULL) )
{ printf("Error no se puede abrir uno o varios ar hivos de datos\n");
exit(1);
}
signal(SIGINT,salir); /* Atrapar la llamada de la fun ion de salida trl- */
Ini iarGraf();
y1 = 0.5;
srand48(1); /* poner semilla */
for (i=0;;i+=0.01) /* in rementar i siempre */
{
/* usar trl- para salir del programa */
y2 = (float) drand48();
if (i == 0.0)
y3 = 0.0;
else
y3 = sin(DEG_TO_RAD(1.0/i));
y4 = sin(DEG_TO_RAD(i));
/* argar ar hivos */
fprintf(fp1,"%f %f\n",i,y1);
fprintf(fp2,"%f %f\n",i,y2);
fprintf(fp3,"%f %f\n",i,y3);
fprintf(fp4,"%f %f\n",i,y4);
/* asegurarse que los buffers son opiados al dis o */
/* para que gnuplot pueda leer los datos
*/
fflush(fp1);
fflush(fp2);
fflush(fp3);
fflush(fp4);
/* grafi ar alot graph */
Graf1Vez();
usleep(10000); /* dormir por un orto tiempo (250 mi rosegundos) */
}
}
void salir()
{
printf("\n trl- atrapada:\n Terminando las tuberias\n");
PararGrafi a();
printf("Cerrando los ar hivos de datos\n");
f lose(fp1);
f lose(fp2);
f lose(fp3);

 ENTRE PROCESOS (IPC INTERPROCESS COMMUNICATION), PIPES130


CAPITULO 22. COMUNICACION

f lose(fp4);
printf("Borrando los ar hivos de datos\n");
BorrarDat();
}

El modulo grafi ador. es el siguiente:


/**********************************************************************/
/* modulo: grafi ador.
*/
/* Contiene rutinas para grafi ar un ar hivo de datos produ ido por */
/* programa. En este aso se grafi a en dos dimensiones
*/
/**********************************************************************/
#in lude "externals.h"
stati FILE *plot1,
*plot2,
*ashell;

stati har *ini iargraf1 = "plot [ [0:1.1 'plot11.dat' with lines, 'plot12.dat' with lines\n"
stati har *ini iargraf2 = "plot 'plot21.dat' with lines, 'plot22.dat' with lines\n";
stati
stati
stati
stati

har
har
har
har

* omando1= "/usr/bin/gnuplot> dump1";


* omando2= "/usr/bin/gnuplot> dump2";
*borrar hivos = "rm plot11.dat plot12.dat plot21.dat plot22.dat";
*set_term = "set terminal x11\n";

void Ini iarGraf(void)


{
plot1 = popen( omando1, "w");
fprintf(plot1, "%s", set_term);
fflush(plot1);
if (plot1 == NULL)
exit(2);
plot2 = popen( omando2, "w");
fprintf(plot2, "%s", set_term);
fflush(plot2);
if (plot2 == NULL)
exit(2);
}
void BorrarDat(void)
{
ashell = popen(borrar hivos, "w");
exit(0);
}

 ENTRE PROCESOS (IPC INTERPROCESS COMMUNICATION), PIPES131


CAPITULO 22. COMUNICACION

void PararGrafi a(void)


{
p lose(plot1);
p lose(plot2);
}
void Graf1Vez(void)
{
fprintf(plot1, "%s", ini iargraf1);
fflush(plot1);
fprintf(plot2, "%s", ini iargraf2);
fflush(plot2);
}

El ar hivo de abe era externals.h ontiene lo siguiente:


/* externals.h */
#ifndef EXTERNALS
#define EXTERNALS
#in lude <stdio.h>
#in lude <stdlib.h>
#in lude <math.h>
/* prototipos */

Con la nalidad de tener un mejor ontrol en la ompila ion del programa se luede usar el siguiente ar hivo
Makefile:
FUENTES. = grafi a. grafi ador.
INCLUDES=
CFLAGS=
SLIBS= -lm
PROGRAMA= grafi a
OBJETOS= $(FUENTES. :. =.o)
$(PROGRAMA): $(INCLUDES) $(OBJETOS)
g -o $(PROGRAMA) $(OBJETOS) $(SLIBS)
grafi a.o: externals.h grafi a.
g - grafi a.
grafi ador.o: externals.h grafi ador.
g - grafi ador.

 ENTRE PROCESOS (IPC INTERPROCESS COMMUNICATION), PIPES132


CAPITULO 22. COMUNICACION

lean:
rm -f $(PROGRAMA) $(OBJETOS)

También podría gustarte