Está en la página 1de 151

ManualdeC

HctorTejedaVillela

ndiceGeneral

1.CompilacindeunprogramaenC/C++

1.1Creacin,compilacinyejecucindeunprograma

1.1.1Creacindelprograma

1.1.2Compilacin

1.1.3Ejecucindelprograma

1.2ElmodelodecompilacindeC

1.3Elpreprocesador

1.4CompiladordeC

1.5Ensamblador

1.6Ligador

1.7Algunasopcionestilesdelcompilador

1.8Usodelasbibliotecas

1.9Ejemplos

1.9.1Creacindeunabibliotecaesttica

1.9.2Creacindeunabibliotecacompartida

1.10FuncionesdelabibliotecadeUNIX

1.10.1Encontrandoinformacinacercadelasbibliotecas.

1.11Ejercicios

2.PrincipiosdeC
2.1OrgenesdelC

2.2CaractersticasdeC

2.3EstructuradeunprogramaenC

2.4Variables

2.4.1Definicindevariablesglobales

2.4.2Lecturayescrituradevariables

2.5Constantes

2.6OperadoresAritmticos

2.7OperadoresdeComparacin

2.8Operadoreslgicos

2.9Ordendeprecedencia

2.10Ejercicios

3.EstructurasCondicionales
3.1Lasentencia

if

3.2Eloperador

?

3.3Lasentencia

switch

3.4Ejercicios

4.Iteracin
4.1Lasentencia

for

4.2Lasentencia

while

4.3Lasentencia

dowhile

4.4Usode

break

y
continue

4.5Ejercicios

5.Arreglosycadenas
5.1Arreglosunidimensionalesymultidimensionales

5.2Cadenas

5.3Ejercicios

6.Funciones
6.1Funciones

void

6.2Funcionesyarreglos

6.3Prototiposdefunciones

6.4Ejercicios

7.Mstiposdedatos
7.1Estructuras

7.1.1Definicindenuevostiposdedatos

7.2Uniones

7.3Conversindetipos(casts)

7.4Enumeraciones

7.5Variablesestticas

7.6Ejercicios

8.Apuntadores
8.1Definicindeunapuntador

8.2ApuntadoresyFunciones

8.3Apuntadoresyarreglos

8.4Arreglosdeapuntadores

8.5Arreglosmultidimensionalesyapuntadores

8.6Inicializacinestticadearreglosdeapuntadores

8.7Apuntadoresyestructuras

8.8Fallascomunesconapuntadores

8.9Ejercicios

9.AsignacindinmicadememoriayEstructurasdinmicas
9.1Usode

malloc,sizeof

y
free

9.2
calloc

y
realloc

9.3Listasligadas

9.4Programaderevisin

9.5Ejercicios

10.Tpicosavanzadosconapuntadores
10.1Apuntadoresaapuntadores

10.2Entradaenlalneadecomandos

10.3Apuntadoresafunciones

10.4Ejercicios

11.Operadoresdebajonivelycamposdebit
11.1Operadoressobrebits

11.2Camposdebit

11.2.1Portabilidad

11.3Ejercicios

12.ElpreprocesadordeC
12.1Directivasdelpreprocesador

12.1.1

#define

12.1.2

#undef

12.1.3

#include

12.1.4

#if
Inclusincondicional

12.2Controldelpreprocesadordelcompilador

12.3Otrasdirectivasdelpreprocesador

12.4Ejercicios

13.C,UNIXylasbibliotecasestndar
13.1VentajasdelusarUNIXconC

13.2Usodefuncionesdebibliotecasyllamadasdelsistema

14.Biblioteca<stdlib.h>

14.1Funcionesaritmticas

14.2Nmerosaleatorios

14.3Conversindecadenas

14.4Bsquedayordenamiento

14.5Ejercicios

15.Biblioteca<math.h>

15.1Funcionesmatemticas

15.2Constantesmatemticas

16.Entradaysalida(E/S)stdio.h

16.1Reportandoerrores

16.1.1

perror()

16.1.2

errno

16.1.3

exit

16.2Flujos

16.2.1Flujospredefinidos

16.3E/SBasica

16.4E/Sformateada

16.4.1

printf

16.4.2

scanf

16.5Archivos

16.5.1Lecturayescrituradearchivos

16.6
sprintf

y
sscanf

16.6.1Peticindelestadodelflujo

16.7E/Sdebajonivelosinalmacenamientointermedio

16.8Ejercicios

17.Manejodecadenas<string.h>

17.1Funcionesbsicasparaelmanejodecadenas

17.1.1Bsquedaencadenas

17.2Pruebayconversindecaracteres

<ctype.h>

17.3Operacionesconlamemoria

<memory.h>

17.4Ejercicios

18.AccesodeArchivosyllamadasalsistemadedirectorios
18.1Funcionesparaelmanejodedirectorios

<unistd.h>

18.1.1Busquedayordenamientodedirectorios:

sys/types.h
,sys/dir.h

18.2Rutinasdemanipulacindearchivos:unistd.h,sys/types.h,sys/stat.h

18.2.1Permisosdeaccesosaarchivos

18.2.2Estadodeunarchivo

18.2.3Manipulacindearchivos:stdio.h,unistd.h

18.2.4Creacindearchivostemporales:

<stdio.h>

18.3Ejercicios

19.Funcionesparaeltiempo
19.1Funcionesbsicasparaeltiempo

19.2Ejemplosdeaplicacionesdefuncionesdeltiempo.

19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralgnclculo.

19.2.2Ejemplo2:Inicializarlasemilladeunnmeroaleatorio.

19.3Ejercicios

20.Controldeprocesos:<stdlib.h>

,<unistd.h>

20.1EjecutandocomandosdeUNIXdesdeC

20.2

execl()

20.3

fork()

20.4

wait()

20.5

exit()

20.6Ejercicios

21.CompilacindeProgramasconArchivosMltiples
21.1ArchivosCabezera

21.2VariablesyFuncionesExternas

21.2.1Alcancedelasvariablesexternas

21.3VentajasdeUsarVariosArchivos

21.4Comodividirunprogramaenvariosarchivos

21.5OrganizacindelosDatosencadaArchivo

21.6LautileraMake

21.6.1ProgramandoMake

21.7CreacindeunArchivoMake(Makefile)

21.8UsodemacrosconMake

21.9Ejecucinde

Make

22.Comunicacinentreprocesos(IPCInterprocessCommunication),PIPES
22.1EntubandoenunprogramadeC

<stdio.h>

22.1.1

popen()

Tuberaformateada

22.1.2

pipe()

Tuberadebajonivel

23.Sockets
23.1Creacinynombradodesockets

23.2Conectandosocketsdeflujo

23.2.1Transferenciadedatosenunflujoycerrado

Sobreestedocumento...

ltimamodificacin:20050812
HctorTejedaV
htejeda@fismat.umich.mx

Subsecciones

1.1Creacin,compilacinyejecucindeunprograma
1.1.1Creacindelprograma

1.1.2Compilacin

1.1.3Ejecucindelprograma

1.2ElmodelodecompilacindeC

1.3Elpreprocesador

1.4CompiladordeC

1.5Ensamblador

1.6Ligador

1.7Algunasopcionestilesdelcompilador

1.8Usodelasbibliotecas

1.9Ejemplos

1.9.1Creacindeunabibliotecaesttica

1.9.2Creacindeunabibliotecacompartida

1.10FuncionesdelabibliotecadeUNIX
1.10.1Encontrandoinformacinacercadelasbibliotecas.

1.11Ejercicios

1.CompilacindeunprogramaenC/C++
EnestacaptulosedanlasprocesosbsicosqueserequierenparacompilarunprogramadeC.Se
describetambinelmodelodecompilacindeCytambincomoCsoportabibliotecasadicionales.

1.1Creacin,compilacinyejecucindeun
programa
1.1.1Creacindelprograma
Sepuedecrearunarchivoquecontengaelprogramacompleto,comoenlosejemplosquesetienen
msadelante.Sepuedeusarcualquiereditordetextosordinarioconelqueseestefamiliarizado.Un
editordisponibleenlamayoradelossistemasUNIXesvi,yenLinuxsepuedeusarpico.
Porconvencinelnombredelarchivodebeterminarcon``.c''porejemplo:miprograma.c
progprueba.c.ElcontenidodelarchivodeberobedecerlasintaxisdeC.

1.1.2Compilacin
ExistenmuchoscompiladoresdeC.ElcceselcompiladorestndardeSun.ElcompiladorGNUde
Cesgcc,elcualesbastantepopularyestadisponibleenvariasplataformas.
ExistentambincompiladoresequivalentesdeC++loscualesusualmentesonnombradoscomoCC.
Porejemplo,SunproveeCCyGNUGCC.ElcompiladordeGNUestambindenotadocomog++.
ExistenotroscompiladoresmenoscomunesdeCyC++.Engeneraltodosloscompiladores
mencionadosoperanesencialmentedelamismaformaycompartenmuchasopcionescomunesen
lalneadeopciones.Msadelanteselistanysedanejemplosdeopcionescomunesdelos
compiladores.Sinembargo,lamejorreferenciadecadacompiladoresatravsdelaspginasen
lnea,delmanualdelsistema.Porejemplo:mangcc.
Paracompilarelprogramausaremoselcomandogcc.Elcomandodeberserseguidoporel
nombredelprogramaenCquesequierecompilar.Undeterminadonmerodeopcionesdel
compiladorpuedenserindicadastambin.Porelmomentonoharemosusodeestasopciones
todava,seirncomentandoalgunasmsesenciales.
Porlotanto,elcomandobsicodecompilacines:
gccprograma.c

dondeprograma.ceselnombredelarchivo.
Sihayerroresobviosenelprograma(talescomopalabrasmalescritas,caracteresnotecleadosu
omisionesdepuntoycoma),elcompiladorsedetendrylosreportar.
Podrahaberdesdeluegoerroreslgicosqueelcompiladornopodrdetectar.Enelcasoqueesta
fueralasituacinseleestarindicandoalacomputadoraquehagalasoperacionesincorrectas.
Cuandoelcompiladorhaterminadoconxito,laversincompilada,oelejecutable,esdejadoenun
archivollamadoa.out,osilaopcinoesusadaconelcompilador,elnombredespusdeoesel
nombredelprogramacompilado.
Serecomiendayesmsconvenienteusarlaopcinoconelnombredelarchivoejecutablecomose
muestraacontinuacin:
gccoprogramaprograma.c

elcualponeelprogramacompiladoenelarchivodelprogramasealado,enstecasoenprograma,
envezdelarchivoa.out.

1.1.3Ejecucindelprograma
Elsiguienteestadoescorrerelprogramaejecutable.ParacorrerunejecutableenUNIX,
simplementeseescribeelnombredelarchivoquelocontiene,enestecasoprograma(oa.out).
Conloanterior,seejecutaelprograma,mostrandoalgnresultadoenlapantalla.Ensteestado,

podrahabererroresentiempodeejecucin(runtimeerrors),talescomodivisinporcero,obien,
podranhacerseevidentesalverqueelprogramanoproducelasalidacorrecta.
Siloanteriorsucede,entoncessedeberegresaraeditarelarchivodelprograma,recompilarlo,y
ejecutarlonuevamente.

1.2ElmodelodecompilacindeC
Enlafigura1.1semuestranlasdistintastapasquecubreelcompiladorparaobtenerelcdigo
ejecutable.

Figura1.1:ModelodecompilacindeC.

1.3Elpreprocesador
Estapartedelprocesodecompilacinsercubiertaconmsdetalleenelcaptulo12referenteal
preprocesador.Sinembargo,sedaalgunainformacinbsicaparaalgunosprogramasdeC.
Elpreprocesadoraceptaelcdigofuentecomoentradayesresponsablede:

quitarloscomentarios
interpretarlasdirectivasdelpreprocesadorlascualesiniciancon#.

Porejemplo:

#includeincluyeelcontenidodelarchivonombrado.Estossonusualmentellamados
archivosdecabecera(header).Porejemplo:
#include<math.h>Archivodelabibliotecaestndardematemticas.
#include<stdio.h>ArchivodelabibliotecaestndardeEntrada/Salida.

#definedefineunnombresimblicooconstante.Sustitucindemacros.
#defineTAM_MAX_ARREGLO100

1.4CompiladordeC
ElcompiladordeCtraduceelcdigofuenteencdigodeensamblador.Elcdigofuenteesrecibido
delpreprocesador.

1.5Ensamblador
Elensambladorcreaelcdigofuenteiolosarchivosobjeto.EnlossistemasconUNIXsepodrn
verlosarchivosconelsufijo.o.

1.6Ligador
Sialgnarchivofuentehacereferenciaafuncionesdeunabibliotecaodefuncionesqueestn
definidasenotrosarchivosfuentes,elligadorcombinaestasfunciones(conmain())paracrearun
archivoejecutable.Lasreferenciasavariablesexternasenestatapasonresueltas.

1.7Algunasopcionestilesdelcompilador
Descritoelmodelobsicodecompilacin,sedarnalgunasopcionestilesyalgunasveces
esenciales.Denuevacuenta,serecomiendarevisarlaspginasdemanparamayorinformaciny
opcionesadicionales.
E
Secompiladorsedetieneenlatapadepreprocesamientoyelresultadosemuestraenla
salidaestndar.
gccEarch1.c
c
Suprimeelprocesodeligadoyproduceunarchivo.oparacadaarchivofuentelistado.
Despuslosarchivosobjetopuedenserligadosporelcomandogcc,porejemplo:
gccarch1.oarch2.o...oejecutable
lbiblioteca
Ligaconlasbibliotecasobjeto.Estaopcindeberseguirlosargumentosdelos

archivosfuente.Lasbibliotecasobjetosonguardadasypuedenestarestandarizadas,un
terceroousuariolascrea.Probablementelabibliotecamscomnmenteusadaesla
bibliotecamatemtica(math.h).Estabibliotecadeberligarseexplcitamentesise
deseausarlasfuncionesmatemticas(yporsupuestonoolvidarelarchivocabecera
#include<math.h>,enelprogramaquellamaalasfunciones),porejemplo:
gcccalc.cocalclm
Muchasotrasbibliotecassonligadasdeestaforma.
Ldirectorio
Agregadirectoriosalalistadedirectoriosquecontienenlasrutinasdelabibliotecade
objetos.Elligadorsiemprebuscalasbibliotecasestndaresydelsistemaen/liby
/usr/lib.Sisequierenligarbibliotecaspersonalesoinstaladasporusted,setendr
queespecificardondeestanguardadoslosarchivos,porejemplo:
gccprog.cL/home/minombr/mislibsmilib.a
Itrayectoria
Agregaunatrayectoriaorutaalalistadedirectoriosenloscualessebuscarnlos
archivoscabecera#includeconnombresrelativos(esdecir,losquenoempiezancon
diagonal/).
Elprocesadorpordefault,primerobuscalosarchivos#includeeneldirectorioque
contieneelarchivofuente,ydespusenlosdirectoriosnombradosconlaopcinIsi
hubiera,yfinalmente,en/usr/include.Porlotanto,sisequiereincluirarchivosde
cabeceraguardadosen/home/minombr/miscabecerassetendrquehacer:
gccprog.cI/home/minombr/miscabeceras
Nota:Lascabecerasdelasbibliotecasdelsistemasonguardadosenunlugarespecial
(/usr/include)ynosonafectadasporlaopcinI.Losarchivoscabeceradel
sistemaydelusuariosonincludosenunamaneraunpocodiferente.
g
Opcinparallamarlasopcionesdedepuracin(debug).Instruyealcompiladorpara
producirinformacinadicionalenlatabladesmbolosqueesusadoporunavariedadde
utilerasdedepuracin.Porejemplo,siseempleaeldepuradordeGNU,elprograma
debercompilarsedelasiguienteformaparagenerarextensionesdeGDB:
gccggdboprogprog.c
D
Definesmboloscomoidentificadores(Didentificador)ocomovalores
(Dsmbolo=valor)enunaformasimilaraladirectivadelpreprocesador#define).

v
Muestraenlasalidaestandardeerroresloscomandosejecutadosenlastapasde
compilacin.

1.8Usodelasbibliotecas
Cesunlenguajeextremadamentepequeo.Muchasdelasfuncionesquetienenotroslenguajesno
estnenC,porejemplo,nohayfuncionesparaE/S,manejodecadenasofuncionesmatemticas.
LafuncionalidaddeCseobtieneatravsdeunricoconjuntodebibliotecasdefunciones.
Comoresultado,muchasimplementacionesdeCincluyenbibliotecasestndardefuncionespara
variasfinalidades.ParamuchospropsitosbsicosestaspodranserconsideradascomopartedeC.
Peropuedenvariardemquinaamquina.
Unprogramadorpuedetambindesarrollarsuspropiasfuncionesdebibliotecaeinclusobibliotecas
especialesdeterceros,porejemplo,NAGoPHIGS.
Todaslasbibliotecas(exceptoE/Sestndar)requierenserexplcitamenteligadasconlaopcinly,
posiblementeconL,comosesealopreviamente.

1.9Ejemplos
1.9.1Creacindeunabibliotecaesttica
Sisetieneunconjuntoderutinasqueseusenenformafrecuente,sepodradesearagruparlasenun
conjuntodearchivosfuente,compilarcadaarchivofuenteenunarchivoobjeto,yentoncescrearuna
bibliotecaconlosarchivosobjeto.Conloanteriorsepuedeahorrartiempoalcompilarenaquellos
programasdondeseanusadas.
Supongamosquesetieneunconjuntodearchivosquecontenganrutinasquesonusadas
frecuentemente,porejemplounarchivocubo.c:
floatcubo(floatx)
{
return(x*x*x);
}

yotroarchivofactorial.c
intfactorial(intn)
{
inti,res=1;
for(i=1;i<=n;i++)
res*=i;
return(res);

Paralosarchivosdenuestrasfuncionestambinsedebetenerunarchivodecabezera,paraque
puedanserusadas,suponiendoquesetieneelsiguientearchivolibmm.hconelsiguiente
contenido:
externfloatcubo(float);
externintfactorial(int);

Elcdigoqueuselabibliotecaqueseestacreandopodraser:
/*Programaprueba.c*/
#include"libmm.h"
#defineVALOR4
main()
{
printf("Elcubode%des%f\n",VALOR,cubo(VALOR));
printf("\tysufactoriales%d\n",factorial(VALOR));
}

Paracrearlabibliotecasedebencompilarlosarchivosfuente,quelopodemoshacerdelasiguiente
forma:
$gccccubo.cfactorial.c

Locualnosdejarlosarchivoscubo.oyfactorial.o.Despussedebecrearlabibliotecaconlos
archivosfuentes,suponiendoquenuestrabibliotecasellamelibmm.a,tendrsquehacerloconel
comandoaras:
$arrlibmm.acubo.ofactorial.o

Cuandoseactualizaunabiblioteca,senecesitaborrarelarchivoanterior(libmm.a).Elltimo
pasoescrearunndiceparalabiblioteca,loquepermitequeelligadorpuedaencontrarlasrutinas.
Loanterior,lohacemosconelcomandoranlib,porloqueteclearemosahora:
$ranliblibmm.a

Losltimosdospasospudieronsercombinadosenunoslo,entonceshubieramospodidoteclear:
$arrslibmm.acubo.ofactorial.o

Ahoraqueyatenemoslabiblioteca,esconvenientequecoloquemosnuestrabibliotecayelarchivo
cabezeraenalgnlugarapropiado.Supongamosquedejamoslabibliotecaen~/libyelfichero
cabezeraen~/include,debemoshacerlosiguiente:
$mkdir../include
$mkdir../lib
$mvlibmm.h../include
$mvlibmm.a../lib

Sillegarsamodificarlabiblioteca,tendrasquerepetirlaltimainstruccin.
Sedebeahoracompilarelarchivoconlabiblioteca,delasiguienteforma:

gccI../includeL../libopruebaprueba.clmm

1.9.2Creacindeunabibliotecacompartida
Lasventajasquepresentanlasbibliotecascompartidas,eslareduccinenelconsumodememoria,
sisonusadaspormsdeunproceso,ademsdelareduccindeltamaodelcdigoejecutable.
Tambinsehaceeldesarrollomsfcil,yaquecuandosehacealgncambioenlabiblioteca,nose
necesitarecompilaryreenlazarlaaplicacincadavez.Serequiereloanteriorslosisemodificoel
nmerodeargumentosconlosquesellamaunafuncinosecambioeltamaodealguna
estructura.
Elcdigodelabibliotecacompartidanecesitaserindependientedelaposicin,parahacerposible
queseausadoelcdigoporvariosprogramas.Paracrearlabibliotecahacerlodelasiguienteforma:
$gcccfPICcubo.cfactorial.c

Paragenerarlabibliotecadinmicahacerlosiguiente:
$gccsharedolibmm.socubo.ofactorial.o

Noexisteunpasoparalaindexacincomoocurreenlasbibliotecasestticas.
Despushabrquemoverlabibliotecadinmicaasudirectoriocorrespondiente(../lib)y
procederacompilarparaquenuestrocdigouselabiblioteca.
$gccI../includeL../libopruebaprueba.clmm

Nospreguntamosquesucedesihayunabibliotecacompartida(libmm.so)yunaesttica
(libmm.a)disponibles.Enestecaso,elligadorsiempretomalacompartida.Sisedeseahaceruso
delaesttica,setendrquenombrarexplcitamenteenlalneadecomandos:
$gccI../includeL../libopruebaprueba.clibmm.a

Cuandoseusanbibliotecascompartidasuncomandotilesldd,elcualnosinformaque
bibliotecascompartidasunprogramaejecutableusa,acontinuacinunejemplo:
$lddprueba
libstuff.so=>libstuff.so(0x40018000)
libc.so.6=>/lib/i686/libc.so.6(0x4002f000)
/lib/ldlinux.so.2=>/lib/ldlinux.so.2(0x40000000)

Comoseveencadalneaapareceelnombredelabiblioteca,elcaminocompletoalabibliotecaque
esusada,ydondeenelespaciodedireccionesvirtualeslabibliotecaestamapeada.
Silddmuestracomosalidanotfoundparaalgunabiblioteca,sevanatenerproblemasyel
programanopodraserejecutado.Unaformadearreglarloesbuscarlabibliotecaycolocarlaenel
lugarcorrectoparaqueelprogramaloaderlaencuentre,quesiemprebuscapordefaultenliby
/usr/lib.Sisetienenbibliotecasenotrodirectorio,crearunavariabledeambiente
LD_LIBRARY_PATHyponerlosdirectoriosseparadospor;.

1.10FuncionesdelabibliotecadeUNIX
ElsistemaUNIXdaungrannmerodefuncionesdeC.Algunasimplementanoperacionesdeuso
frecuente,mientrasotrasestnmuyespecializadasenrelacinasuaplicacin.
Noreinventelarueda.Serecomiendarevisarsiunafuncinenalgunabibliotecaexiste,envezde
hacerlatareadeescribirsupropiaversin.Conloanteriorsereduceeltiempodedesarrollodeun
programa.Yaquelasfuncionesdelabibliotecahansidoprobadas,porloqueestarncorregidas,a
diferenciadecualquieraqueunprogramadorpuedaescribir.Loanteriorreducireltiempode
depuracindelprograma.

1.10.1Encontrandoinformacinacercadelasbibliotecas.
ElmanualdeUNIXtieneunaentradaparatodaslasfuncionesdisponibles.Ladocumentacinde
funcionesestaguardadaenlaseccin3delmanual,yhaymuchasotrastilesquehacenllamadasal
sistemaenlaseccin2.Siyasabeelnombredelafuncinquesequiererevisar,puedeleerla
pginatecleando:
man3sqrt
Sinosabeelnombredelafuncin,unalistacompletaestaincluidaenlapginaintroductoriadela
seccin3delmanual.Paraleerlo,teclee:
man3intro
Hayaproximadamente700funciones.Elnmerotiendeaincrementarseconcadaactualizacinal
sistema.
Encualquierpginadelmanual,laseccindeSYNOPSISincluyeinformacindelusodela
funcin.Porejemplo:
#include<time.h>
char*ctime(consttime_t*timep);
Loquesignificaquesedebetener
#include<time.h>
enelarchivodelprogramaquehaceelllamadoactime.Yquelafuncinctimetomaun
apuntadordeltipotime_tcomounargumento,yregresaunacadenachar*.
EnlaseccinDESCRIPTIONsedaunapequeadescripcindeloquehacelafuncin.

1.11Ejercicios
1. Escribe,compilaycorreelsiguienteprograma.Modificaelprogramaparaqueincluyastu
nombreylaformacomohicistesloanterior.Parainiciaruncomentariousa/*ypara
terminarlo*/:
main()
{
inti;
printf("\tNumero\t\tCubo\n\n");
for(i=0;i<=20;++i)
printf("\t%d\t\t\t%d\n",i,i*i*i);
}

2. Elsiguienteprogramausalabibliotecamatemtica.Teclalo,compilaloyejecutalo.Incluye
concomentariosdentrodelprogramatunombreylaformacomohicistesloanterior.
#include<math.h>
main()
{
inti;
printf("\tAngulo\t\tSeno\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. Buscaenlosdirectorios/liby/usr/liblasbibliotecasqueestndisponibles.Manda3
nombresdeestticasy3decompartidas.

Useelcomandomanparaobtenerdetallesdelasfuncionesdelabiblioteca.
Seleccionaalgunabibliotecayveloscdigosobjetosquecontiene,puedesteclear:
artvbiblioteca

4. Veen/usr/includequearchivosdecabeceraestndisponibles.
Usaloscomandosmoreocatparaverlosarchivosdetexto.
Exploralosarchivoscabeceraparaverelcontenido,observandolasdirectivasde
preprocesamientoinclude,define,lasdefinicionesdelostiposylosprototiposdelas
funciones.Envia10casosdondesehayanusadolasdirectivasanteriores,indicando
dequearchivodecabezeralasobtuvistes.
5. SupongamosquesetieneunprogramaenCelcualtienelafuncinprincipalenmain.cy
quesetienenotrasfuncionesenlosarchivosinput.cyoutput.c:
Dequformahabraquecompilaryligaresteprograma?
Cmosedebernmodificarloscomandosanterioresparaligarunabiblioteca
llamadaproceso1guardadaeneldirectorioestndardelasbibliotecasdel
sistema?
Cmomodificarasloscomandosanterioresparaligarunabibliotecallamada
proceso2guardadaentudirectoriocasa?
Algunosarchivoscabeceranecesitanserledosyencontradosenelsubdirectorio

headerdesudirectoriocasaytambinendirectoriodetrabajoactual.Cmose
modificaranloscomandosdecompilacinparahacerlosealado?

Subsecciones
2.1OrgenesdelC

2.2CaractersticasdeC

2.3EstructuradeunprogramaenC

2.4Variables

2.4.1Definicindevariablesglobales

2.4.2Lecturayescrituradevariables

2.5Constantes

2.6OperadoresAritmticos

2.7OperadoresdeComparacin

2.8Operadoreslgicos

2.9Ordendeprecedencia

2.10Ejercicios

2.PrincipiosdeC
EnestecaptuloseofreceunabrevehistoriadeldesarrollodellenguajeCyseconsiderantambin
suscaractersticas.
EnelrestodelcaptulosevenlosaspectosbsicosdelosprogramasdeC,talescomosuestructura,
ladeclaracindevariables,tiposdedatosyoperadores.

2.1OrgenesdelC
ElprocesodedesarrollodellenguajeCseoriginaconlacreacindeunlenguajellamadoBCPL,
quefuedesarrolladoporMartinRichards.ElBCPLtuvoinfluenciaenunlenguajellamadoB,el
cualseusen1970yfueinventadoporKenThompsonyquepermitieldesarrollodeCen1971,el
cualloinventeimplementDennisRitchie.Para1973elsistemaoperativoUNIXestabacasi
totalmenteescritoenC.
DurantemuchosaoselestndarparaCfuelaversin5delsistemaoperativoUNIX,documentada
en``TheCProgrammingLanguage''escritoporBrianW.KernighanandDennisM.Ritchiein1978
comnmentereferidocomoK&R.
Posteriormentesehicieronvariasimplementacioneslascualesmostrabanlassiguientestendencias:

Nuevascaractersticas
Diferenciasdemquinas
Diferenciasdeproductos
Erroresenloscompiladores
Malasimplementaciones

Estooriginqueenelveranode1983seestablecierauncomitpararesolverestasdiscrepancias,el
cualempezatrabajarenunestndarANSIC,lacualfuecompletadaen1988.

2.2CaractersticasdeC
Algunasdelascaractersticasmsimportantesquedefinenellenguajeyquehanpermitidoquesea
tanpopular,comolenguajedeprogramacinson:

Tamaopequeo.
Usoextensivodellamadasafunciones.
Comandosbreves(pocotecleo).
Lenguajeestructurado.
Programacindebajonivel(nivelbit)
Implementacindeapuntadoresusoextensivodeapuntadoresparalamemoria,arreglos,
estructurasyfunciones

Lasdiversasrazonesporlacualsehaconvertidoenunlenguajedeusoprofesionalson:

Elusodeconstructoresdealtonivel.
Elpodermanejaractividadesdebajonivel.
Elgenerarprogramaseficientes.
Laposibilidaddepodersercompiladoenunavariedaddecomputadoras,conpocoscambios
(portabilidad).

Unpuntoencontraesquetieneunadeteccinpobredeerrores,locualenocasioneses
problemticoparalosprincipiantes.

2.3EstructuradeunprogramaenC
UnprogramadeCtienebsicamentelasiguienteforma:

Comandosdelpreprocesador.
Definicionesdetipos.
Prototiposdefuncionesdeclaraeltipodefuncinylasvariablespasadasalamisma.
Variables
Funciones

Paraunprogramasedebetenerunafuncinmain().
Unafuncintienelaforma:
tiponombre_de_la_funcion(parmetros)
{
variableslocales

sentenciasdeC

Siladefinicindeltipoesomitida,Casumequelafuncinregresauntipoentero.Nota:Lo
anteriorpuedeserunafuentedeproblemasenunprograma.
Acontinuacinsemuestraunprimerprograma:
/*Programaejemplo*/

main()
{

printf("MegustaC\n");
exit(0);

NOTAS:

Crequiereunpuntoycomaalfinaldecadasentencia.
printfesunafuncinestndardeC,lacualesllamadaenlafuncinmain().
\nsignificasaltodelnea.Salidaformateada.
exit()estambinunafuncinestndarquehacequeelprogramatermine.Enelsentido
estrictonoesnecesarioyaqueeslaltimalneademain()ydecualquierformaterminar
elprograma.

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

Lasalidatendralasiguienteforma:
.1
..2
...3

2.4Variables
Ctienelossiguientestiposdedatossimples:
Tabla2.1:TiposdeC
Tipo

Tamao(bytes) Lmiteinferior Lmitesuperior

char

unsignedchar

shortint

unsignedshortint

(long)int

float

double

Lostiposdedatosbsicostienevariosmodificadoresquelespreceden.Seusaunmodificadorpara
alterarelsignificadodeuntipobaseparaqueencajeconlasdiversasnecesidadesosituaciones.Los
modificadoresson:signed,unsigned,longyshort.
EnlossistemasUNIXtodoslostiposintsonlongint,amenosqueseespecifique
explcitamenteshortint.
Nota:nohayuntipobooleanoenCsedeberusarchar,intoanmejorunsignedchar.
signed,unsigned,longyshortpuedenserusadosconlostiposchareint.Aunquees
permitidoelusodesignedenenteros,esredundanteporqueladeclaracindeenteropordefecto
asumeunnmeroconsigno.
ParadeclararunavariableenC,sedebeseguirelsiguienteformato:
tipolista_variables;
tipoesuntipovlidodeCylista_variablespuedeconsistirenunoomsindentificadores
separadosporunacoma.Unidentificadordebecomenzarconunaletraounguinbajo.
Ejemplo:
inti,j,k;
floatx,y,z;
charch;

2.4.1Definicindevariablesglobales
Unavaribleglobalsedeclarafueradetodaslasfunciones,incluyendoalafuncinmain().Una
variableglobalpuedeserutilizadaencualquierpartedelprograma.
Porejemplo:
shortnumero,suma;
intnumerogr,sumagr;
charletra;
main()
{
...
}

Estambinposiblepreinicializarvariablesglobalesusandoeloperadordeasignacin=,por
ejemplo:
floatsuma=0.0;
intsumagr=0;
charletra='A';
main()
{
...
}

Queeslomismoque:
floatsuma;
intsumagr;
charletra;
main()
{
suma=0.0;
sumagr=0;
letra='A';
...
}

DentrodeCtambinsepermitelaasignacinmltipleusandoeloperador=,porejemplo:
a=b=c=d=3;

...queeslomismo,peromseficienteque:
a=3;
b=3;
c=3;
d=3;

Laasignacinmltiplesepuedellevaracabo,sitodoslostiposdelasvariablessoniguales.
SepuedenredefinirlostiposdeCusandotypedef.Comounejemplodeunsimpleusose
consideracomosecreandosnuevostiposrealyletra.Estosnuevostipospuedenserusadosdeigual
formacomolostipospredefinidosdeC.
typedeffloatreal;
typedefcharletra;
/*Declaraciondevariablesusandoelnuevotipo*/
realsuma=0.0;
letrasig_letra;

2.4.2Lecturayescrituradevariables
EllenguajeCusasalidaformateada.Lafuncinprintftieneuncaracterespecialparaformatear
(%)uncaracterenseguidadefineunciertotipodeformatoparaunavariable.

%ccaracteres
%scadenadearacteres
%denteros
%fflotantes
Porejemplo:
printf("%c%d%f",ch,i,x);

Lasentenciadeformatoseencierraentre"",yenseguidalasvariables.Asegurarsequeelorden
deformateoylostiposdedatosdelasvariablescoincidan.
scanf()eslafuncinparaentrarvaloresavariables.Suformatoessimilaraprintf.Por
ejemplo:
scanf("%c%d%f%s",&ch,&i,&x,cad);

Observarqueseantepone&alosnombresdelasvaribles,exceptoalacadenadecaracteres.Enel
captulo8quetratasobreapuntadoresserevisarmsafondoelusodeesteoperador.

2.5Constantes
ANSICpermitedeclararconstantes.Cuandosedeclaraunaconstanteesunpocoparecidoa
declararunavariable,exceptoqueelvalornopuedesercambiado.
Lapalabraclaveconstseusaparadeclararunaconstante,comosemuestraacontinuacin:
consta=1;
inta=2;

Notas:

Sepuedeusarconstantesodespusdeltipo.
Esusualinicializarunaconstanteconunvalor,yaquenopuedesercambiadadealgunaotra
forma.

Ladirectivadelpreprocesador#defineesunmtodomsflexibleparadefinirconstantesenun
programa.
Frecuentementeseveladeclaracinconstenlosparmetrosdelafuncin.Loanterior
simplementeindicaquelafuncinnocambiaraelvalordelparmetro.Porejemplo,lasiguiente
funcinusaesteconcepto:
char*strcpy(char*dest,constchar*orig);
ElsegundoargumentoorigesunacadenadeCquenoseralterada,cuandoseuselafuncinde
labibliotecaparacopiarcadenas.

2.6OperadoresAritmticos
Lomismoqueenotroslenguajesdeprogramacin,enCsetienenlosoperadoresaritmticosms
usuales(+suma,resta,*multiplicacin,/divisiny%mdulo).
Eloperadordeasignacines=,porejemplo:i=4;ch='y';
Incremento++ydecrementounario.Loscualessonmseficientesquelasrespectivas
asignaciones.Porejemplo:x++esmsrpidoquex=x+1.
Losoperadores++ypuedenserprefijosopostfijos.Cuandosonprefijos,elvalorescalculado
antesdequelaexpresinseaevaluada,ycuandoespostfijoelvalorescalculadodespusquela
expresinesevaluada.
Enelsiguienteejemplo,++zesprefijoyespostfijo:
intx,y,z;
main()
{
x=((++z)(y))%100;
}

Queesequivalentea:
intx,y,z;
main()
{
z++;
x=(zy)%100;
y;
}

Eloperador%(mdulooresiduo)solamentetrabajaconenteros,aunqueexisteunafuncinpara
flotantes(15.1fmod())delabibliotecamatemtica.
Eloperadordivisin/esparadivisinenterayflotantes.Porlotantohayquetenercuidado.El
resultadodex=3/2;esuno,ansixesdeclaradocomofloat.Lareglaes:siambos
argumentosenunadivisinsonenteros,entoceselresultadoesentero.Sisedeseaobtenerla
divisinconlafraccin,entoncesescribirlocomo:x=3.0/2;ox=3/2.0yan
mejorx=3.0/2.0.
Porotraparte,existeunaformamscortaparaexpresarclculosenC.Porejemplo,sisetienen
expresionescomo:i=i+3;ox=x*(y+2);,puedenserreescritascomo:

Locualesequivalente,peromenoseficienteque:

Porloquepodemosreescribirlasexpresionesanteriorescomo:i+=3;yx*=y+2;
respectivamente.

2.7OperadoresdeComparacin
Eloperadorparaprobarlaigualdades==,porloquesedebertenercuidadodenoescribir
accidentalmenteslo=,yaque:
if(i=j)...
EsunasentencialegaldeC(sintcticamentehablandoaunqueelcompiladoravisacuandose
emplea),lacualcopiaelvalorde``j''en``i'',locualserinterpretadocomoVERDADERO,sij
esdiferentedecero.
Diferentees!=,otrosoperadoresson:<menorque,>mayorque,<=menorqueoigualay>=
(mayorqueoiguala).

2.8Operadoreslgicos
Losoperadoreslgicossonusualmenteusadosconsentenciascondicionalesorelacionales,los
operadoresbscioslgicosson:
&&Ylgico,||Olgicoy!negacin.

2.9Ordendeprecedencia
Esnecesariosercuidadososconelsignificadodeexpresionestalescomoa+b*c,
dependiendodeloquesedeseehacer
(a+b)*c
o
a+(b*c)
Todoslosoperadorestienenunaprioridad,losoperadoresdemayorprioridadsonevaluadosantes
quelosquetienenmenorprioridad.Losoperadoresquetienenlamismaprioridadsonevaluadosde
izquierdaaderecha,porloque:
abc
esevaluadocomo
(ab)c

Prioridad Operador(es)
Msalta ()[]>
!~++(tipo)*&sizeof
*/%
+
<<>>
<<=>>=
==!=
&
^
|
&&
||
?
=+==*=/=
Msbaja ,
Deacuerdoaloanterior,lasiguienteexpresin:
a<10&&2*b<c
Esinterpretadacomo:
(a<10)&&((2*b)<c)
y
a=
b=
10/5
+2;

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

2.10Ejercicios
EscribirprogramasenCparahacerlassiguientestareas:

1. Leerlaentradadedosnmerosymostrareldobleproductodelprimeromenoslamitaddel
segundo.
2. Leayescribasunombre,apellidopaterno,apellidomaternoymatriculaenunformato
adecuado.
3. Escribirunprogramaparaleerun``flotante''querepresentaunnmerodegradosCelsius,e
imprimecomoun``flotante''latemperaturaequivalenteengradosFahrenheit.Lasalida
puedeserdelasiguienteforma:100.0gradosCelsiusson212.0grados
Fahrenheit.
4. Escribirunprogramaparaimprimirvariasveceselejercicio2.Puedeusarvarias
instruccionesprintf,conuncaracterdenuevalneaencadauna,ounainstruccinconvarios
caracteresnuevalneaenlacadenadeformateo.
5. Escribirunprogramaqueleaelradiodeuncrculocomounnmeroflotanteymuestreel
reayelpermetrodelcrculo.
6. Dadosciertoscentmetroscomoentradadetipoflotante,imprimirsuequivalenciaapies
(enteros)ypulgadas(flotante,1decimal),dandolaspulgadasconunaprecisindeunlugar
decimalSuponer2.54centmetrosporpulgada,y12pulgadasporpie.
Silaentradaes333.3,elformatodelasalidadeberser:
333.3centmetrosson10pies11.2pulgadas.

Subsecciones

3.1Lasentenciaif

3.2Eloperador
?

3.3Lasentencia
switch

3.4Ejercicios

3.EstructurasCondicionales
EnestecaptuloserevisanlosdistintosmtodosconlosqueCcontrolaelflujolgicodeun
programa.
Comoserevisenelcaptuloanterior,losoperadoresrelacionesbinariosqueseusanson:
==,!=,<,<=,>y>=
ademslosoperadoreslgicosbinarios:
||,&&
yeloperadorlgicounariodenegacin!,queslotomaunargumento.
Losoperadoresanteriorsonusadosconlassiguientesestructurasquesemuestran.

3.1Lasentenciaif
Lastresformascomosepuedeemplearlasentenciaifson:
if(condicion)
sentencia;
...o
if(condicion)
sentencia1;
else
sentencia2;
...o

if(condicion1)
sentencia1;
elseif(condicion2)
sentencia2;
...
else
sentencian;
Elflujolgicodeestaestructuraesdearribahaciaabajo.Laprimerasentenciaseejecutaryse
saldrdelaestructuraifsilaprimeracondicinesverdadera.Silaprimeracondicinfuefalsa,y
existeotracondicin,seevala,ysilacondicinesverdadera,entoncesseejecutalasentencia
asociada.Siexistenmscondicionesdentrodelaestructuraif,sevanevaluandostas,siemprey
cuandolascondicionesqueleprecedanseanfalsas.
Lasentenciaqueestaasociadaalapalabrareservadaelse,seejecutasitodaslascondicionesdela
estructuraiffueronfalsas.
Porejemplo:
main()
{
intx,y,w;
........
if(x>0)
{
z=w;
.......
}
else
{
z=y;
.......
}
}

3.2Eloperador?
Eloperadorternariocondicional?esmseficientequelasentenciaif.Eloperador?tieneel
siguienteformato:
expresion1?expresion2:expresion3;
Queesequivalentealasiguienteexpresin:
if(expresion1)thenexpresion2elseexpresion3;

Porejemplo,paraasignarelmximodeaybalavariablez,usando?,tendramos:
z=(a>b)?a:b;
queeslomismoque:
if(a>b)
z=a;
else
z=b;

Elusodeloperador?parareemplazarlassentenciasif...elsenoserestringesloa
asignaciones,comoenelejemploanterior.Sepuedenejecutarunaomsllamadasdefuncin
usandoeloperador?ponindolasenlasexpresionesqueformanlosoperandos,comoenelejemplo
siguiente:
f1(intn)
{
printf("%d",n);
}
f2()
{
printf("introducido\n");
}
main()
{
intt;
printf(":");
scanf("%d",&t);
/*imprimemensajeapropiado*/
t?f1(t)+f2():printf("Sediuncero\n");
}

3.3Lasentenciaswitch
Aunqueconlaestructuraif...elseifsepuedenrealizarcomprobacionesmltiples,en
ocasionesnoesmuyelegante,yaqueelcdigopuedeserdifcildeseguirypuedeconfundirincluso
alautortranscurridountiempo.Porloanterior,Ctieneincorporadaunasentenciadebifurcacin
mltiplellamadaswitch.Conestasentencia,lacomputadoracompruebaunavariable
sucesivamentefrenteaunalistadeconstantesenterasodecaracter.Despusdeencontraruna
coincidencia,lacomputadoraejecutalasentenciaobloquedesentenciasqueseasocianconla
constante.Laformageneraldelasentenciaswitches:
switch(variable){
caseconstante1:
secuenciadesentencias
break;

caseconstante2:
secuenciadesentencias
break;
caseconstante3:
secuenciadesentencias
break;
...
default:
secuenciadesentencias
}
dondelacomputadoraejecutalasentenciadefaultsinocoincideningunaconstanteconla
variable,estaltimaesopcional.Cuandoseencuentraunacoincidencia,lacomputadoraejecutalas
sentenciasasociadasconelcasehastaencontrarlasentenciabreakconloquesaledela
estructuraswitch.
Laslimitacionesquetienelasentenciaswitch...caserespectoalaestructuraifson:

Slosetieneposibilidadderevisarunasolavariable.
Conswitchslosepuedecomprobarporigualdad,mientrasqueconifpuedesercon
cualquieroperadorrelacional.
Nosepuedeprobarmsdeunaconstanteporcase.

Laformacomosepuedesimularelltimopunto,esnoteniendosentenciasasociadosauncase,
esdecir,teniendounasentencianuladondesloseponeelcaso,conloquesepermitequeelflujo
delprogramacaigaalomitirlassentencias,comosemuestraacontinuacin:
switch(letra)
{
case'a':
case'e':
case'i':
case'o':
case'u':
numvocales++;
break;
case'':
numesp++;
break;
default:
numotras++;
break;
}

3.4Ejercicios
1. Escribirunprogramaqueleadoscaracteres,eimprimasuvalorcuandosepuedainterpretar
comounnmerohexadecimal.Aceptarletrasmaysculasyminsculasparalosvaloresdel
10al15.
2. Leerunvalorentero.Suponerqueelnmeroesundadelasemana.Suponerque0
correspondeaDomingoyassucesivamente.Imprimirelnombredelda.
3. Dadoscomoentrada3enterosrepresentandolafechacomoda,mes,ao,imprimirlafecha
deldaanterior.Porejemploparaunaentradacomo:131992Lasalidaser:Fechaanterior
a131992es29021992
4. Escribirunprogramaelcualleadosvaloresenteros.Sielprimeroesmenorqueelsegundo,
queimprimaelmensaje``Arriba''.Sielsegundoesmenorqueelprimero,queimprimael
mensaje``Abajo''.Silosnmerossoniguales,queimprimaelmensaje``igual''.Sihayun
errorenlalecturadelosdatos,queimprimaunmensajeconteniendolapalabra``Error''y
hagaexit(0);

Subsecciones

4.1Lasentenciafor

4.2Lasentencia
while

4.3Lasentencia
dowhile

4.4Usode
break

y
continue

4.5Ejercicios

4.Iteracin
EnestecaptuloserevisanlosmecanismosdeCpararepetiruncojuntodeinstruccioneshastaque
secumpleciertacondicin.

4.1Lasentenciafor
Lasentenciafortieneelsiguienteformato:
for(expresion1;expresion2;expresion3)
sentencia;
o{bloquedesentencias}
Endondeexpresion1seusapararealizarlainicializacindevariables,usandounaovarias
sentencias,siseusanvariassentenciasdeberusarseeloperador,parasepararlas.Porlogeneral,
estableceelvalordelavariabledecontroldelciclo.expresion2seusaparalacondicinde
terminacindelcicloyexpresion3eselmodificadoralavariabledecontroldelciclocadavez
quelacomputadoralorepite,perotambinpuedesermsqueunincremento.
Porejemplo:
intX;
main()
{
for(X=3;X>0;X)
{
printf("X=%d\n",X);
}
}

generalasiguientesalidaapantalla...
X=3
X=2
X=1

TodoslassiguientessentenciasforsonvlidasenC.Lasaplicacionesprcticasdetalessentencias

nosonimportantesaqu,yaquetansloseintentailustraralguanascaractersticasquepuedenser
deutilidad:
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)

Enelsegundoejemplosemuestralaformacomomltiplesexpresionespuedenaparecer,siemprey
cuandoestnseparadasporunacoma,
Eneltercerejemplo,elciclocontinuariterandohastaquezseconviertaen .

4.2Lasentenciawhile
LasentenciawhileesotrocicloobucledisponibleenC.Suformatoes:
while(expresion)sentencia;
dondesentenciapuedeserunasentenciavaca,unasentencianicaounbloquedesentenciasquese
repetirn.Cuandoelflujodelprogramallegaaestainstruccin,primeroserevisasilacondicines
verdadparaejecutarla(s)sentencia(s),ydespuselciclowhileserepetirmientraslacondicin
seaverdadera.Cuandollegaaserfalsa,elcontroldelprogramapasaalalneaquesiguealciclo.
Enelsiguienteejemplosemuetraunarutinadeentradadesdeelteclado,lacualseciclamientrasno
sepulseA:
main()
{
charcarac;
carac='\0';
while(carac!='A')carac=getchar();
}

Antesdeentraralcicloseinicializalavariablecaracanulo.Despuspasaalasentenciawhile
dondesecompruebasicaracnoesiguala'A',comoseaverdadentoncesseejecutalasentencia
delbucle(carac=getchar();).Lafuncingetchar()leeelsiguientecarcterdelflujo
estndar(teclado)ylodevuelve,queennuestroejemploeselcaracterquehayasidotecleado.Una
vezquesehapulsadounatecla,seasignaacaracysecompruebalacondicinnuevamente.
DespusdepulsarA,lacondicinllegaaserfalsaporquecaracesigualaA,conloqueelciclo
termina.
Deloanterior,setienequetantoelciclofor,comoelciclowhilecompruebanlacondicinenlo
altodelciclo,porloqueelcdigodentrodelciclonoseejecutasiempre.
Acontinuacinmostramosotroejemplo:
main()
{
intx=3;

while(x>0)
{
printf("x=%d\n",x);
x;
}
}

quegeneralasiguientesalidaenpantalla:
x=3
x=2
x=1

Comoseobserva,dentrodelciclotenemosmsdeunasentencia,porloqueserequiereusarlallave
abiertaylallavecerrada{...}paraqueelgrupodesentenciasseantratadascomounaunidad.
Comoelciclowhilepuedaaceptartambinexpresiones,ynosolamentecondicioneslosiguiente
esvlido:
while(x);
while(x=x+1);
while(x+=5);

Siseusanestetipodeexpresiones,solamentecuandoelresultadodex,x=x+1ox+=5sea
cero,lacondicinfallarysepodrsalirdelciclo.
Deacuerdoaloanterior,podemosrealizarunaoperacincompletadentrodelaexpresin.Por
ejemplo:
main()
{
charcarac;
carac='\0';
while((carac=getchar())!='A')
putchar(carac);
}

Enesteejemploseusanlasfuncionesdelabibliotecaestndargetchar()leeuncaracterdel
tecladoyputchar()escribeuncaracterdadoenpantalla.Elciclowhileprocederaleerdel
tecladoylomostrarhastaqueelcaracterAsealedo.

4.3Lasentenciadowhile
Alcontrariodelosciclosforywhilequecompruebanlacondicinenloaltodelbucle,elbucle
do...whilelaexaminaenlapartebajadelmismo.Estacaractersticaprovocaqueunciclo
do...whilesiempreseejecutealmenosunavez.Laformageneraldelcicloes:
do{
sentencia;

}while(condicin);
Aunquenosonnecesariaslasllavescuandosloestpresenteunasentencia,seusannormalmente
porlegibilidadyparaevitarconfusin(respectoallector,ynodelcompilador)conlasentencia
while.
Enelsiguienteprogramaseusaunciclodo...whileparaleernmerosdesdeeltecladohasta
queunodeellosesmenorqueoiguala100:
main()
{
intnum;
do
{
scanf("%d",&num);
}while(num>100);
}

Otrousocomndelaestructurado...whileesunarutinadeseleccinenunmen,yaque
siempreserequierequeseejecutealmenosunavez.
main()
{
intopc;
printf("1.Derivadas\n");
printf("2.Limites\n");
printf("3.Integrales\n");
do
{
printf("Teclearunaopcion:");
scanf("%d",&opc);
switch(opc)
{
case1:
printf("\tOpcion1seleccionada\n\n");
break;
case2:
printf("\tOpcion2seleccionada\n\n");
break;
case3:
printf("\tOpcion3seleccionada\n\n");
break;
default:
printf("\tOpcionnodisponible\n\n");
break;
}
}while(opc!=1&&opc!=2&&opc!=3);
}

Semuestraunejemplodondesereescribeusandodo...whileunodelosejemplosya
mostrados.
main()
{
intx=3;
do

{
printf("x=%d\n",x);
}
while(x>0);
}

4.4Usodebreakycontinue
Comosecomentounodelosusosdelasentenciabreakesterminaruncaseenlasentencia
switch.Otrousoesforzarlaterminacininmediatedeunciclo,saltandolapruebacondicional
delciclo.
Cuandoseencuentralasentenciabreakenunbucle,lacomputadoraterminainmediatamenteel
cicloyelcontroldelprogramapasaalasiguientesenteciadelciclo.Porejemplo:
main()
{
intt;
for(t=0;t<100;t++)
{
printf("%d",t);
if(t==10)break;
}
}

Esteprogramamuestraenpantallalosnmerosdel0al10,cuandoalcanzaelvalor10secumplela
condicindelasentenciaif,seejecutalasentenciabreakysaledelciclo.
Lasentenciacontinuefuncionademanerasimilaralasentenciabreak.Sinembargo,envezde
forzarlasalida,continuefuerzalasiguienteiteracin,porloquesaltaelcdigoquefaltapara
llegaraprobarlacondicin.Porejemplo,elsiguienteprogramavisualizarslolosnmerospares:
main()
{
intx;

for(x=0;x<100;x++)
{
if(x%2)
continue;
printf("%d",x);
}
}

Finalmenteseconsideraelsiguienteejemplodondeseleenvaloresenterosyseprocesandeacuerdo
alassiguientescondiciones.Sielvalorquesealedoesnegativo,sedeseaimprimirunmensajede
erroryseabandonaelciclo.Sielvaloresmayorque100,seignoraysecontinualeyendo,ysiel
valorescero,sedeseaterminarelciclo.
main()
{
intvalor;
while(scanf("%d",&valor)==1&&valor!=0)
{
if(valor<0)

{
printf("Valornovalido\n");
break;
/*Salirdelciclo*/
}
if(valor>100)
{
printf("Valornovalido\n");
continue;
/*Pasaralprincipiodelciclonuevamente*/
}
printf("Segarantizaqueelvalorleidoestaentre1y100");
}
}

4.5Ejercicios
1. Escribirunprogramaquelea5nmerosyencuentreelpromedio,elmximoyelmnimode
esosvalores.
2. Escribirunprogramaqueleanmeroshastaqueseencuentreelcero.Elsegundonmerose
sumaralprimero,luegoelterceroserestar,elcuartosesumar,yassedeberseguir
alternadohastaqueselleguealcero.Cuandosellegueaestacondiciondeberimprimirel
resultado,eltotaldeoperandosdelaoperacin(sinincluirelcero),ylasumadelos
operandosqueserestaron.
3. Escribirunprogramaqueleaunvalorenteroqueserlabaseparaunsistemanumrico
(binario,octalodecimal),despusqueleaunenteropositivoenesabaseyqueimprimasu
valorenbase10.Sedebevalidarqueelnmeropertenezcaaesabase.Labasesermenor
queoiguala10.Elprogramapodratenerlasiguientesalida:
EntradaSalida
BaseNumero
=======================
1012341234
87763
2111115

4. Escribirunprogramaqueleaunnmeroenbase10yloconviertaabase2,base8ybase
hexadecimal.
5. Leertresvaloresrepresentandolosiguiente:
Elcapital(nmeroenterodepesos)
Unatasadeinteresenporciento(flotante)
yunnmerodeaos(entero).
Calcularlosvaloresdelasumadelcapitalyelinterescompuestoparaunperododadode
aos.Paracadaaoelinteresescalculadocomo:interes=capital*
tasa_interes/100;
elcualsesumaalcapital
capital+=interes;

Imprimirlosvaloresdemonedaconunaprecisindedosdecimales.Imprimirlosvalores
delinterscompuestoparacadaaoalfinaldelperodo.Lasalidapuedesercomola
siguiente:
Capitalinicial35000.00contasadel12.50en10aos
AoInteresSuma
++
14375.0039375.00
24921.8844296.88
35537.1149833.98
46229.2556063.23
57007.9063071.14
67883.8970955.03
78869.3879824.41
89978.0589802.45
911225.31101027.76
1012628.47113656.23

6. Leerunvalorpositivo,yhacerlasiguientesecuencia:sielnmeroespar,dividirloentre2;
siesnon,multiplicarlopor3ysumarle1.Repetirloanteriorhastaqueelvalorsea1,
imprimiendocadavalor,tambinsedeberimprimircuantasoperacionesdeestasson
hechas.
Unasalidapodraserlasiguiente:
Elvaloriniciales9
Elsiguientevalores28
Elsiguientevalores14
Elsiguientevalores7
Elsiguientevalores22
Elsiguientevalores11
Elsiguientevalores34
Elsiguientevalores17
Elsiguientevalores52
Elsiguientevalores26
Elsiguientevalores13
Elsiguientevalores40
Elsiguientevalores20
Elsiguientevalores10
Elsiguientevalores5
Elsiguientevalores16
Elsiguientevalores8
Elsiguientevalores4
Elsiguientevalores2
Valorfina11,numerodepasos19.

Sielvaloringresadoesmenorque1,imprimirunmensajequecontengalapalabra
Error
yhaga
exit(0)

Subsecciones

5.1Arreglosunidimensionalesymultidimensionales

5.2Cadenas

5.3Ejercicios

5.Arreglosycadenas
Enelsiguientecaptulosepresentanlosarreglosylascadenas.Lascadenasseconsiderancomoun
arreglodetipochar.

5.1Arreglosunidimensionalesy
multidimensionales
Losarreglossonunacoleccindevariablesdelmismotipoquesereferencianutilizandounnombre
comn.Unarregloconstadeposicionesdememoriacontigua.Ladireccinmsbajacorrespondeal
primerelementoylamsaltaalltimo.Unarreglopuedetenerunaovariasdimensiones.Para
accederaunelementoenparticulardeunarregloseusaunndice.
Elformatoparadeclararunarreglounidimensionales:
tiponombre_arr[tamao]
Porejemplo,paradeclararunarreglodeenterosllamadolistanumcondiezelementossehacedela
siguienteforma:
intlistanum[10];

EnC,todoslosarreglosusancerocomondiceparaelprimerelemento.Portanto,elejemplo
anteriordeclaraunarreglodeenteroscondiezelementosdesdelistanum[0]hastalistanum[9].
Laformacomopuedenseraccesadosloselementosdeunarreglo,esdelasiguienteforma:
listanum[2]=15;/*Asigna15al3erelementodelarreglolistanum*/
num=listanum[2];/*Asignaelcontenidodel3erelementoalavariablenum*/

EllenguajeCnorealizacomprobacindecontornosenlosarreglos.Enelcasodequesobrepaseel
finalduranteunaoperacindeasignacin,entoncesseasignarnvaloresaotravariableoauntrozo
delcdigo,estoes,sisedimensionaunarreglodetamaoN,sepuedereferenciarelarreglopor
encimadeNsinprovocarningnmensajedeerrorentiempodecompilacinoejecucin,incluso

aunqueprobablementeseprovoqueelfallodelprograma.Comoprogramadorseesresponsablede
asegurarquetodoslosarreglosseanlosuficientementegrandesparaguardarloquepondrenellos
elprograma.
Cpermitearreglosconmsdeunadimensin,elformatogenerales:
tiponombre_arr[tam1][tam2]...[tamN];
Porejemplounarreglodeenterosbidimensionalesseescribircomo:
inttabladenums[50][50];

Observarqueparadeclararcadadimensinllevasuspropiosparntesiscuadrados.
Paraaccederloselementosseprocededeformasimilaralejemplodelarreglounidimensional,esto
es,
tabladenums[2][3]=15;/*Asigna15alelementodela3filayla4columna*/
num=tabladenums[25][16];

Acontinuacinsemuestraunejemploqueasignaalprimerelementodeunarreglobidimensional
cero,alsiguiente1,yassucesivamente.
main()
{
intt,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");
}
}

EnCsepermitelainicializacindearreglos,debiendoseguirelsiguienteformato:
tiponombre_arr[tam1][tam2]...[tamN]={listavalores};
Porejemplo:
inti[10]={1,2,3,4,5,6,7,8,9,10};
intnum[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

5.2Cadenas
Adiferenciadeotroslenguajesdeprogramacinqueempleanuntipodenominadocadenastring
paramanipularunconjuntodesimbolos,enC,sedebesimularmedianteunarreglodecaracteres,

endondelaterminacindelacadenasedebeindicarconnulo.Unnuloseespecificacomo'\0'.
Porloanterior,cuandosedeclareunarreglodecaracteressedebeconsideraruncarcteradicionala
lacadenamslargaquesevayaaguardar.Porejemplo,sisequieredeclararunarreglocadena
queguardeunacadenadediezcaracteres,seharcomo:
charcadena[11];

SepuedenhacertambininicializacionesdearreglosdecaracteresendondeautomticamenteC
asignaelcaracternuloalfinaldelacadena,delasiguienteforma:
charnombre_arr[tam]="cadena";
Porejemplo,elsiguientefragmentoinicializacadenacon``hola'':
charcadena[5]="hola";

Elcdigoanterioresequivalentea:
charcadena[5]={'h','o','l','a','\0'};

Paraasignarlaentradaestndaraunacadenasepuedeusarlafuncinscanfconlaopcin%s
(observarquenoserequiereusareloperador&),deigualformaparamostrarloenlasalidaestndar.
Porejemplo:
main()
{
charnombre[15],apellidos[30];

printf("Introducetunombre:");
scanf("%s",nombre);
printf("Introducetusapellidos:");
scanf("%s",apellidos);
printf("Ustedes%s%s\n",nombre,apellidos);
}

EllenguajeCnomanejacadenasdecaracteres,comosehaceconenterosoflotantes,porloquelo
siguientenoesvlido:
main()
{
charnombre[40],apellidos[40],completo[80];
nombre="JosMara";/*Ilegal*/
apellidos="MorelosyPavn";/*Ilegal*/
completo="Gral."+nombre+appellidos;/*Ilegal*/
}

5.3Ejercicios
1. Escribirunprogramaqueleaunarreglodecualquiertipo(entero,flotante,char),sepodra
pediralusuarioqueindiqueeltipodearreglo,ytambinescribirunprogramaquereviseel
arregloparaencontrarunvalorenparticular.

2. Leeruntexto,uncaracteralavezdesdelaentradaestndar(queeselteclado),eimprimir
cadalneaenformainvertida.Leerhastaqueseencuentreunfinaldedatos(teclar
CONTROLDparagenerarlo).
Elprogramapodraprobarsetecleandoprogrev|progrevparaversiunacopia
exactadelaentradaoriginalesrecreada.
Paraleercaractereshastaelfinaldedatos,sepuedeusarunciclocomoelsiguiente
charch;
while(ch=getchar(),ch>=0)/*ch<0indicafindedatos*/

o
charch;
while(scanf("%c",&ch)==1)/*seleeuncaracter*/

3. Escribirunprogramaparaleeruntextohastaelfindedatos,ymostrarunaestadsticadelas
longitudesdelaspalabras,estoes,elnmerototaldepalabrasdelongitud1quehayan
ocurrido,eltotaldelongitud2yassucesivamente.
Defineunapalabracomounasecuenciadecaracteresalfabticos.Sedebernpermitir
palabrashastadeunalongitudde25letras.
Unasalidatpicapodrasercomoesta:
longitud1:16ocurrencias
longitud2:20ocurrencias
longitud3:5ocurrencias
longitud4:2ocurrencias
longitud5:0ocurrencias
........

Subsecciones

6.1Funcionesvoid

6.2Funcionesyarreglos

6.3Prototiposdefunciones

6.4Ejercicios

6.Funciones
Unafuncinesunconjuntodedeclaraciones,definiciones,expresionesysentenciasquerealizan
unatareaespecfica.
ElformatogeneraldeunafuncinenCes
especificador_de_tiponombre_de_funcin(lista_de_parmetros)
{
variableslocales
cdigodelafuncin
}
Elespecificador_de_tipoindicaeltipodelvalorquelafuncindevolvermedianteelusode
return.Elvalorpuedeserdecualquiertipovlido.Sinoseespecficaunvalor,entoncesla
computadoraasumepordefectoquelafuncindevolverunresultadoentero.Nosetienensiempre
queincluirparmetrosenunafuncin.lalistadeparmetrospuedeestarvaca.
Lasfuncionesterminanyregresanautomticamentealprocedimientoquelasllamcuandose
encuentralaltimallave},obien,sepuedeforzarelregresoantesusandolasentenciareturn.
Ademasdelusosealadolafuncinreturnseusaparadevolverunvalor.
Seexaminaacontinuacinunejemploqueencuentraelpromediodedosenteros:
floatencontprom(intnum1,intnum2)
{
floatpromedio;

promedio=(num1+num2)/2.0;
return(promedio);
}
main()
{
inta=7,b=10;
floatresultado;

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

6.1Funcionesvoid
Lasfuncionesvoiddanunaformadeemular,loqueenotroslenguajesseconocencomo
procedimientos(porejemplo,enPASCAL).Seusancuandonorequiereregresarunvalor.Se
muestraunejemploqueimprimeloscuadradosdeciertosnmeros.
voidcuadrados()
{
intcontador;
for(contador=1;contador<10;contador++)
printf("%d\n",contador*contador);
}
main()
{
cuadrados();
}

Enlafuncincuadradosnoestadefinidoningnparmetro,yporotrapartetampocoseempleala
sentenciareturnpararegresardelafuncin.

6.2Funcionesyarreglos
Cuandoseusanunarreglocomounargumentoalafuncin,sepasasloladireccindelarregloy
nolacopiadelarregloentero.Parafinesprcticospodemosconsiderarelnombredelarreglosin
ningnndicecomoladireccindelarreglo.
Considerarelsiguienteejemploendondesepasaunarregloalafuncinimp_rev,observarque
noesnecesarioespecificarladimensindelarreglocuandoesunparmetrodelafuncin.
voidimp_rev(chars[])
{
intt;
for(t=strlen(s)1;t>=0;t)
printf("%c",s[t]);
}
main()
{
charnombre[]="Facultad";
imp_rev(nombre);
}

Observarqueenlafuncinimp_revseusalafuncinstrlenparacalcularlalongituddela
cadenasinincluirelterminadornulo.Porotraparte,lafuncinimp_revnousalasentencia
returnniparaterminardeusarlafuncin,nipararegresaralgnvalor.

Semuestraotroejemplo,
floatenconprom(inttam,floatlista[])
{
inti;
floatsuma=0.0;
for(i=0;i<tam;i++)
suma+=lista[i];
return(suma/tam);
}
main()
{
floatnumeros[]={2.3,8.0,15.0,20.2,44.01,3.0,2.9};
printf("Elpromediodelalistaes%f\n",enconprom(7,numeros));
}

Paraelcasodequesetengaquepasarunarregloconmsdeunadimensin,noseindicalaprimera
dimensinpero,elrestodelasdimensionesdebensealarse.Semuestraacontinuacinunejemplo:
voidimprtabla(inttamx,inttamy,floattabla[][5])
{
intx,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.3Prototiposdefunciones
AntesdeusarunafuncinCdebetenerconocimientoacercadeltipodedatoqueregresaryeltipo
delosparmetrosquelafuncinespera.
ElestndarANSIdeCintrodujunanueva(mejor)formadehacerloanteriorrespectoalas
versionespreviasdeC.
Laimportanciadeusarprototiposdefuncioneseslasiguiente:

Sehaceelcdigomsestructuradoyporlotanto,msfcildeleer.
SepermitealcompiladordeCrevisarlasintaxisdelasfuncionesllamadas.

Loanterioreshecho,dependiendodelalcancedelafuncin.Bsicamentesiunafuncinhasido
definidaantesdequeseausada(ollamada),entoncessepuedeusarlafuncinsinproblemas.
Sinoesas,entonceslafuncinsedebedeclarar.Ladeclaracinsimplementemanejaeltipode
datoquelafuncinregresayeltipodepar^o'ametrosusadosporlafuncin.
Esunaprcticausualyconvenienteescribirelprototipodetodaslasfuncionesalprincipiodel
programa,sinembargoestonoesestrictamentenecesario.

Paradeclararunprototipodeunafuncinseindicareltipodedatoqueregresarlafuncin,el
nombredelafuncinyentreparntesislalistadeltipodelosparmetrosdeacuerdoalordenque
aparecenenladefinicindelafuncin.Porejemplo:
intlongcad(char[]);

Loanteriordeclaraunafuncinllamadalongcadqueregresaunvalorenteroyaceptaunacadena
comoparmetro.

6.4Ejercicios
1. Escribirunafuncin``reemplaza'',lacualtomaunacadenacomoparmetro,lereemplaza
todoslosespaciosdelacadenaporunguinbajo,ydevuelveelnmerodeespacios
reemplazados.Porejemplo:
charcadena[]="Elgatonegro";
n=reemplaza(cadena);

deberdevolver:
cadenaconvertida"El_gato_negro"
n=2

2. Escribirunprogramaqueleaunalneadetextoenunbuffer(unacadenadecaracteres)
usandolafuncingetsycalculelalongituddelalnea(NOusarlafuncinstrlen).
3. Modificarelprogramaanteriorparaqueleaunarchivodetexto.Elarchivodeber
redireccionarsealprograma,debiendomostrarelcontenidodelmismo.Encasodequese
leaunalneaconlongitud0deberterminarelprograma.

Subsecciones

7.1Estructuras
7.1.1Definicindenuevostiposdedatos

7.2Uniones

7.3Conversindetipos(casts)

7.4Enumeraciones

7.5Variablesestticas

7.6Ejercicios

7.Mstiposdedatos
EnestecaptuloserevisalaformacomopuedensercreadosyusadosenCtiposdedatosms
complejosyestructuras.

7.1Estructuras
EnCunaestructuraesunacoleccindevariablesquesereferencianbajoelmismonombre.Una
estructuraproporcionaunmedioconvenienteparamantenerjuntainformacinqueserelaciona.
Unadefinicindeestructuraformaunaplantillaquesepuedeusarparacrearvariablesde
estructura.Lasvariablesqueformanlaestructurasonllamadoselementosestructurados.
Generalmente,todosloselementosenlaestructuraestnrelacionadoslgicamenteunosconotros.
Porejemplo,sepuederepresentarunalistadenombresdecorreoenunaestructura.Mediantela
palabraclavestructseleindicaalcompiladorquedefinaunaplantilladeestructura.
structdirec
{
charnombre[30];
charcalle[40];
charciudad[20];
charestado[3];
unsignedintcodigo;
};

Coneltrozodecdigoanteriornohasidodeclaradaningunavariable,tansloseha
definidoelformato.Paradeclararunavariable,seharcomosigue:
structdirecinfo_direc;

Sepuedendeclararunaomsvariablescuandosedefineunaestructuraentre)y;.Porejemplo:
structdirec
{
charnombre[30];

charcalle[40];
charciudad[20];
charestado[3];
unsignedintcodigo;
}info_direc,binfo,cinfo;

observarquedirecesunaetiquetaparalaestructuraquesirvecomounaformabreve
parafuturasdeclaraciones.Comoenesteltimadeclaracinseindicanlasvariablescon
estaestructura,sepuedeomitirelnombredelaestructuratipo.
Lasestructuraspuedensertambinpreinicializadasenladeclaracin:
structdirecinfo_direc={"VicenteFernandez","Fantasia
2000","Dorado","MMX",12345};

Parareferenciaroaccesarunmiembro(ocampo)deunaestructura,Cproporcionaeloperador
punto.,porejemplo,paraasignarainfo_direcotrocdigo,lohacemoscomo:
info_direc.codigo=54321;

7.1.1Definicindenuevostiposdedatos
Sesealopreviamente(seccin2.4.1)quetypedefsepuedeusarparadefinirnuevosnombresde
datosexplictamente,usandoalgunosdelostiposdedatosdeC,dondesuformatoes:
typedef<tipo><nombre>;
Sepuedeusartypedefparacrearnombresparatiposmscomplejos,comounaestructura,por
ejemplo:
typedefstructdirec
{
charnombre[30];
charcalle[40];
charciudad[20];
charestado[3];
unsignedintcodigo;
}sdirec;
sdirecinfo_direc={"VicenteFernandez","Fantasia2000","Dorado","MMX",12345};

enestecasodirecsirvecomounaetiquetaalaestructurayesopcional,yaquehasido
definidounnuevotipodedato,porloquelaetiquetanotienemuchouso,endonde
sdireceselnuevotipodedatoseinfo_direcesunavariabledeltiposdirec,la
cualesunaestructura.
ConCtambinsepuedentenerarreglosdeestructuras:
typedefstructdirec
{
charnombre[30];
charcalle[40];
charciudad[20];
charestado[3];
unsignedintcodigo;

}info_direc;
info_direcartistas[1000];

porloanterior,artistastiene1000elementosdeltipoinfo_direc.Loanterior
podraseraccesadodelasiguienteforma:
artistas[50].codigo=22222;

7.2Uniones
Unaunionesunavariablelacualpodraguardar(enmomentosdiferentes)objetosdediferentes
tamaosytipos.Cemplealasentenciaunionparacrearunionesporejemplo:
unionnumero
{
shortshortnumero;
longlongnumero;
doublefloatnumero;
}unumero;

conloanteriorsedefineunauninllamadanumeroyunainstanciadeestallamada
unumero.numeroeslaetiquetadelauninytieneelmismocomportamientoquela
etiquetaenlaestructura.
Losmiembrospuedenseraccesadosdelasiguienteforma:
printf("%ld\n",unumero.longnumero);

conlallamadaalafuncinsemuestraelvalordelongnumero.
CuandoelcompiladordeCestareservandomemoriaparalasuniones,siemprecrearunavariable
losuficientementegrandeparaquequepaeltipodevariablemslargodelaunin.
Conlafinalidaddequeelprogramapuedallevarelregistrodeltipodelavariableuninusadaen
unmomentodado,escomntenerunaestructura(conunauninanidada)yunavariablequeindica
eltipodeunin.
Semuestraunejemplodeloanterior:
typedefstruct
{
intmaxpasajeros;
}jet;
typedefstruct
{
intcapac_elev;
}helicoptero;
typedefstruct
{
intmaxcarga;
}avioncarga;

typedefunion
{
jetjetu;
helicopterohelicopterou;
avioncargaavioncargau;
}transporteaereo;
typedefstruct
{
inttipo;
intvelocidad;
transporteaereodescripcion;
}un_transporteaereo

enelejemplosedefineunauninbasedetransporteareoelcualpuedeserunjet,un
helicpteroounaviondecarga.
Enlaestructuraun_transporeaereohayunmiembroparaeltipo,queindicacualesla
estructuramanejadaensemomento.

7.3Conversindetipos(casts)
Cesunodelospocoslenguajesquepermitenlaconversindetipos,estoes,forzarunavariablede
untipoaserdeotrotipo.Loanteriorsepresentacuandovariablesdeuntiposemezclanconlasde
otrotipo.Parallevaracaboloanteriorseusaeloperadordeconversin(cast)().Porejemplo:
intnumeroentero;
floatnumeroflotante=9.87;
numeroentero=(int)numeroflotante;

conlocualseasigna9alavariablenumeroenteroylafraccinesdesechada.
Elsiguientecdigo:
intnumeroentero=10;
floatnumeroflotante;
numeroflotante=(float)numeroentero;

asigna10.0anumeroflotante.ComoseobservaCconvierteelvalordellado
derechodelaasignacinaltipodelladoizquierdo.
Laconversindetipospuedesertambinusadaconcualquiertiposimplededatosincluyendo
char,porlotanto:
intnumeroentero;
charletra='A';
numeroentero=(int)letra;

asigna65(queeselcdigoASCIIde'A')anumeroentero.

Algunasconversionesdetipossonhechasautomticamenteestoesprincipalmenteporla
caractersticadecompatibilidaddetipos.
Unabuenareglaeslasiguiente:Encasodeduda,conversindetipos.
Otrousoesasegurarsequeladivisindenmerossecomportacomoserequiere,yaquesisetienen
dosenteroslaformadeforzarelresultadoaunnmeroflotantees:
numeroflotante=(float)numerent/(float)denoment;

conloqueseaseguraqueladivisindevolverunnmeroflotante.

7.4Enumeraciones
Unaenumeracinesunconjuntodeconstantesenterasconnombreyespecificatodoslosvalores
legalesquepuedetenerunavariabledeltipoenum.
Laformacomosedefineunaenumeracinesdeformaparecidaacomosehaceconlasestructuras,
usandolapalabraclaveenumparaelcomienzodeuntipodeenumeracin.Suformatoes:
enumnombre_enum{lista_de_enumeracin}lista_de_variables;
Esopcionalnombre_enumylista_de_variables.Laprimeraseusaparadeclararlasvariablesde
sutipo.Elsiguientefragmentodefineunaenumeracinllamadadiscoquedeclara
almacenamientoparaserdeesetipo.
enumalmacenamiento{diskette,dd,cd,dvd,cinta};
enumalmacenamientodisco;

Conlasiguientedefinicinydeclaracinsonvlidaslassiguientessentencias:
disco=cd;
if(disco==diskette)
printf("Esde1440Kb\n");

Seinicializaelprimersmbolodeenumeracinacero,elvalordelsegundosmboloa1yas
sucesivamente,amenosqueseinicialicedeotramanera.Portanto,
printf("%d%d\n",dd,cinta)

muestra14enlapantalla.
Sepuedeespecificarelvalordeunoomssmbolosusandouninicializador.Parahacerlo,ponerun
signoigualyunvalorenterodespusdelsmbolo.
Porejemplo,losiguienteasignaelvalor250acd
enumdisco{diskette,duro,cd=250,dvd,cinta};

Porlotantolosvaloresdelossmbolossonlossiguientes:
diskette 0
duro 1
cd 250
dvd 251
cinta 252

7.5Variablesestticas
Csoportacuatroespecificadoresdeclasedealmacenamiento.Son
auto
extern
static
register
Estosespecifcadoresledicenalcompiladorcomoalmacenarlavariablequesigue.Elespecificador
dealmacenamientoprecedealadeclaracindevariablequetieneelformatogeneral:
especif_almacespecif_tipolista_variables;
Seusaelespecificadorautoparadeclararvariableslocales.Sinembargo,raramenteseusaporque
lasvariableslocalessonautopordefecto.
Lasvariablesstaticsonvariablespermanentesensupropiafuncinoarchivo.Sediferenciandelas
variablesglobalesporquesondesconocidasfueradesusfuncionesoarchivo,peromantienensus
valoresentrellamadas.Estacaractersticalashacetilescuandoseescribenfuncionesgeneralesy
bibliotecasdefunciones.
Variablesstaticlocales.Unavariableestticalocalesunavariablelocalqueretienensuvalorentre
llamadasdefuncin,yaqueClescreaunalmacenamientopermanente.Siloanteriornosepudiera
hacer,entoncessetendranqueusarvariablesglobalesqueabriralapuertaaposiblesefectos
laterales.Unejemplodeunafuncinquerequeriratalesvariablesesungeneradordeseriesde
nmerosqueproduceunnmeronuevobasadoenelltimo.
Acontinuacinsemuestraunejemploendondeseanalizaelcomportamientodeunavariableauto
yunavariablestatic
voidstat();/*Prototipodelafuncion*/
main()
{
inti;
for(i=0;i<5;++i)
stat();
}

voidstat()
{
autointa_var=0;
staticints_var=0;
printf("auto=%d,static=%d\n",a_var,s_var);
++a_var;
++s_var;
}

Lasalidadelcdigoanteriores:
auto=0,static=0
auto=0,static=1
auto=0,static=2
auto=0,static=3
auto=0,static=4

Comosepuedeobservarlavariablea_varescreadacadavezquesellamaalafuncin.La
variables_varescreadaenlaprimerallamadaydespusrecuerdasuvalor,esdecir,nose
destruyecuandoterminalafuncin.

7.6Ejercicios
1. Escribirunprogramaqueuseeltipoenumerateparamostrarelnombredeunmes,su
predecesorysusucesor.Elmesseingresardesdeeltecladodandounnmeroentre1y12.
2. Escribirunprogramaquecontengaunafuncinquepuedarecibirdosestructurasque
contienenlascoordenadasenelplanodedospuntosdados,deloscualessedeseaconocersu
puntomedio.

Subsecciones

8.1Definicindeunapuntador

8.2ApuntadoresyFunciones

8.3Apuntadoresyarreglos

8.4Arreglosdeapuntadores

8.5Arreglosmultidimensionalesyapuntadores

8.6Inicializacinestticadearreglosdeapuntadores

8.7Apuntadoresyestructuras

8.8Fallascomunesconapuntadores

8.9Ejercicios

8.Apuntadores
LosapuntadoressonunapartefundamentaldeC.Siustednopuedeusarlosapuntadores
apropiadamenteentoncesestaperdiendolapotenciaylaflexibilidadqueCofrecebsicamente.El
secretoparaCestaenelusodeapuntadores.
Cusalosapuntadoresenformaextensiva.Porqu?

Eslanicaformadeexpresaralgunosclculos.
Segeneracdigocompactoyeficiente.
Esunaherramientamuypoderosa.

Cusaapuntadoresexplcitamentecon:

Eslanicaformadeexpresaralgunosclculos.
Segeneracdigocompactoyeficiente.
Esunaherramientamuypoderosa.

Cusaapuntadoresexplcitamentecon:

Arreglos,
Estructurasy
Funciones

8.1Definicindeunapuntador
Unapuntadoresunavariablequecontieneladireccinenmemoriadeotravariable.Sepueden
tenerapuntadoresacualquiertipodevariable.

Eloperadorunarioomondico&devuelveladireccindememoriadeunavariable.
Eloperadordeindireccinodereferencia*devuelveel``contenidodeunobjetoapuntadoporun
apuntador''.
Paradeclararunapuntadorparaunavariableenterahacer:
int*apuntador;

Sedebeasociaracadaapuntadoruntipoparticular.Porejemplo,nosepuedeasignarladireccin
deunshortintaunlongint.
Paratenerunamejoridea,considerarelsiguientecdigo:
main()
{
intx=1,y=2;
int*ap;
ap=&x;
y=*ap;
x=ap;
*ap=3;
}

Cuandosecompileelcdigosemostrarelsiguientemensaje:
warning:assignmentmakesintegerfrompointerwithoutacast.
Conelobjetivodeentenderelcomportamientodelcdigosupongamosquelavariablexestaenla
localidaddelamemoria100,yen200yapen1000.Nota:unapuntadoresunavariable,porlo
tanto,susvaloresnecesitanserguardadosenalgnlado.
intx=1,y=2;
int*ap;
ap=&x;

100
x1

200
y2

1000
ap 100

Lasvariablesxeysondeclaradaseinicializadascon1y2respectivamente,apesdeclaradocomo
unapuntadoraenteroyseleasignaladireccindex(&x).Porloqueapsecargaconelvalor100.
y=*ap;

100
x1

200
y1

1000
ap 100

Despusyobtieneelcontenidodeap.Enelejemploapapuntaalalocalidaddememoria100la
localidaddex.Porlotanto,yobtieneelvalordexelcuales1.

x=ap;

100
x 100

200
y1

1000
ap 100

ComosehavistoCnoesmuyestrictoenlaasignacindevaloresdediferentetipo(apuntadora
entero).Asqueesperfectamentelegal(aunqueelcompiladorgeneraunavisodecuidado)asignael
valoractualdeapalavariablex.Elvalordeapenesemomentoes100.
*ap=3;

100
x3

200
y1

1000
ap 100

Finalmenteseasignaunvaloralcontenidodeunapuntador(*ap).
Importante:Cuandounapuntadoresdeclaradoapuntaaalgnlado.Sedebeinicializarel
apuntadorantesdeusarlo.Porloque:
main()
{
int*ap;
*ap=100;
}

puedegenerarunerrorentiempodeejecucinopresentaruncomportamientoerrtico.
Elusocorrectoser:
main()
{
int*ap;
intx;
ap=&x;
*ap=100;
}

Conlosapuntadoressepuederealizartambinaritmticaentera,porejemplo:
main()
{
float*flp,*flq;
*flp=*flp+10;
++*flp;
(*flp)++;
flq=flp;
}

NOTA:Unapuntadoracualquiertipodevariablesesunadireccinenmemorialacualesuna
direccinentera,perounapuntadorNOesunentero.

Laraznporlacualseasociaunapuntadorauntipodedato,esporquesedebeconocerencuantos
bytesestaguardadoeldato.Detalforma,quecuandoseincrementaunapuntador,seincrementael
apuntadorporun``bloque''dememoria,endondeelbloqueestaenfuncindeltamaodeldato.
Porlotantoparaunapuntadoraunchar,seagregaunbytealadireccinyparaunapuntadora
enterooaflotanteseagregan4bytes.Deestaformasiaunapuntadoraflotanteselesuman2,el
apuntadorentoncessemuevedosposicionesfloatqueequivalena8bytes.

8.2ApuntadoresyFunciones
CuandoCpasaargumentosafunciones,lospasaporvalor,esdecir,sielparmetroesmodificado
dentrodelafuncin,unavezqueterminalafuncinelvalorpasadodelavariablepermanece
inalterado.
Haymuchoscasosquesequierealterarelargumentopasadoalafuncinyrecibirelnuevovalor
unavezquelafuncinhaterminado.Parahacerloanteriorsedebeusarunallamadaporreferencia,
enCsepuedesimularpasandounpunteroalargumento.Conestoseprovocaquelacomputadora
paseladireccindelargumentoalafuncin.
Paraentendermejorloanteriorconsideremoslafuncinswap()queintercambiaelvalordedos
argumentosenteros:
voidswap(int*px,int*py);
main()
{
intx,y;
x=10;
y=20;
printf("x=%d\ty=%d\n",x,y);
swap(&x,&y);
printf("x=%d\ty=%d\n",x,y);
}
voidswap(int*px,int*py)
{
inttemp;
temp=*px;/*guardaelvalordeladireccionx*/
*px=*py;/*poneyenx*/
*py=temp;/*ponexeny*/
}

8.3Apuntadoresyarreglos
Existeunarelacinestrechaentrelospunterosylosarreglos.EnC,unnombredeunarregloesun
ndicealadireccindecomienzodelarreglo.Enesencia,elnombredeunarregloesunpunteroal
arreglo.Considerarlosiguiente:
inta[10],x;
int*ap;

ap=&a[0];/*apapuntaaladirecciondea[0]*/
x=*ap;/*Axseleasignaelcontenidodeap(a[0]enestecaso)*/
*(ap+1)=100;/*Seasignaalsegundoelementode'a'elvalor100usando
ap*/

Comosepuedeobservarenelejemplolasentenciaa[t]esidnticaaap+t.Sedebetenercuidadoya
queCnohaceunarevisindeloslmitesdelarreglo,porloquesepuedeirfcilmentemsalladel
arregloenmemoriaysobreescribirotrascosas.
Csinembargoesmuchomsstilensurelacinentrearreglosyapuntadores.Porejemplosepuede
teclearsolamente:
ap=a;envezdeap=&a[0];ytambin*(a+i)envezdea[i],estoes,
&a[i]esequivalentecona+i.
Ycomoseveenelejemplo,eldireccionamientodeapuntadoressepuedeexpresarcomo:
a[i]queesequivalentea*(ap+i)
Sinembargolosapuntadoresylosarreglossondiferentes:

Unapuntadoresunavariable.Sepuedehacerap=ayap++.
UnarregloNOESunavariable.Hacera=apya++ESILEGAL.

Esteparteesmuyimportante,asegresehaberlaentendido.
Conlocomentadosepuedeentendercomolosarreglossonpasadosalasfunciones.Cuandoun
arregloespasadoaunafuncinloqueenrealidadseleestapasandoeslalocalidaddesuelemento
inicialenmemoria.
Porlotanto:
strlen(s)esequivalenteastrlen(&s[0])
Estaeslaraznporlacualsedeclaralafuncincomo:
intstrlen(chars[]);yunadeclaracinequivalenteesintstrlen(char
*s);
yaquechars[]esigualquechar*s.
Lafuncinstrlen()esunafuncindelabibliotecaestndarqueregresalalongituddeunacadena.
Semuestraenseguidalaversindeestafuncinquepodraescribirse:
intstrlen(char*s)
{
char*p=s;
while(*p!='\0')
p++;

returnps;
}

Semuestraenseguidaunafuncinparacopiarunacadenaenotra.Aligualqueenelejercicio
anteriorexisteenlabibliotecaestndarunafuncinquehacelomismo.
voidstrcpy(char*s,char*t)
{
while((*s++=*t++)!='\0');
}

Enlosdosltimosejemplosseempleanapuntadoresyasignacinporvalor.Nota:Seempleaeluso
delcaracternuloconlasentenciawhileparaencontrarelfindelacadena.

8.4Arreglosdeapuntadores
EnCsepuedentenerarreglosdeapuntadoresyaquelosapuntadoressonvariables.
Acontinuacinsemuestraunejemplodesuuso:ordenarlaslneasdeuntextodediferente
longitud.
Losarreglosdeapuntadoressonunarepresentacindedatosquemanejandeunaformaeficientey
convenientelneasdetextodelongitudvariable.
Cmosepuedehacerloanterior?
1. Guardartodaslaslneasenunarreglodetipochargrande.Observandoque\nmarcael
findecadalnea.Verfigura8.1.
2. Guardarlosapuntadoresenunarreglodiferentedondecadaapuntadorapuntaalprimer
caracterdecadalnea.
3. Comparardoslneasusandolafuncindelabibliotecaestndarstrcmp().
4. Sidoslneasestndesacomodadasintercambiar(swap)losapuntadores(noeltexto).

Figura8.1:Arreglosdeapuntadores(Ejemplodeordenamientodecadenas).

Conloanteriorseelimina:
elmanejocomplicadodelalmacenamiento.
altasobrecargaporelmovimientodelneas.

8.5Arreglosmultidimensionalesyapuntadores
UnarreglomultidimensionalpuedeservistoenvariasformasenC,porejemplo:
Unarreglodedosdimensionesesunarreglodeunadimensin,dondecadaunodeloselementoses
ensmismounarreglo.
Porlotanto,lanotacin
a[n][m]

nosindicaqueloselementosdelarregloestnguardadosrenglnporrengln.
Cuandosepasaunaarreglobidimensionalaunafuncinsedebeespecificarelnmerodecolumnas
elnmeroderenglonesesirrelevante.
Larazndeloanterior,esnuevamentelosapuntadores.Crequiereconocercuantassonlas
columnasparaquepuedabrincarderenglnenrenglnenlamemoria.
Considerandoqueunafuncindebarecibirinta[5][35],sepuededeclararelargumentodela
funcincomo:
f(inta[][35]){.....}

oan
f(int(*a)[35]){.....}

Enelltimoejemploserequierenlosparnteis(*a)yaque[]tieneunaprecedenciamsalta
que*.
Porlotanto:
int(*a)[35];declaraunapuntadoraunarreglode35enteros,yporejemplosi
hacemoslasiguientereferenciaa+2,nosestaremosrefiriendoaladireccindelprimer
elementoqueseencuentraneneltercerrenglndelamatrizsupuesta,mientrasque
int*a[35];declaraunarreglode35apuntadoresaenteros.
Ahoraveamosladiferencia(sutil)entreapuntadoresyarreglos.Elmanejodecadenasesuna
aplicacincomndeesto.
Considera:

char*nomb[10];
charanomb[10][20];

Endondeesvlidohacernomb[3][4]yanomb[3][4]enC.
Sinembargo:

anombesunarregloverdaderode200elementosdedosdimensionestipochar.

Elaccesodeloselementosanombenmemoriasehacebajolasiguientefrmula20*renglon
+columna+direccin_base

Encambionombtiene10apuntadoresaelementos.

NOTA:sicadaapuntadorennombindicaunarreglode20elementosentoncesysolamente
entonces200charsestarndisponibles(10elementos).
Conelprimertipodedeclaracinsetienelaventajadequecadaapuntadorpuedeapuntaraarreglos
dediferentelongitud.
Considerar:
char*nomb[]={"Nomes","Ene","Feb","Mar",....};
charanomb[][15]={"Nomes","Ene","Feb","Mar",...};

Locualgrficamentesemuestraenlafigura8.2.Sepuedeindicarquesehaceunmanejoms
eficientedelespaciohaciendousodeunarreglodeapuntadoresyusandounarreglobidimensional.

Figura8.2:Arreglode2dimensionesVS.arreglodeapuntadores.

8.6Inicializacinestticadearreglosde
apuntadores
Lainicializacindearreglosdeapuntadoresesunaaplicacinidealparaunarregloestticointerno,
porejemplo:
func_cualquiera()
{
staticchar*nomb[]={"Nomes","Ene","Feb","Mar",....};
}

Recordandoqueconelespecificadordealmacenamientodeclasestaticsereservaenforma
permanentememoriaelarreglo,mientraselcdigoseestaejecutando.

8.7Apuntadoresyestructuras
Losapuntadoresaestructurassedefinenfcilmenteyenunaformadirecta.Considerarlosiguiente:
main()
{
structCOORD{floatx,y,z;}punto;
structCOORD*ap_punto;
punto.x=punto.y=punto.z=1;
ap_punto=&punto;/*Seasignapuntoalapuntador*/
ap_punto>x++;/*Coneloperador>seaccesanlosmiembros*/
ap_punto>y+=2;/*delaestructuraapuntadosporap_punto*/
ap_punto>z=3;
}

Otroejemplosonlaslistasligadas:
typedefstruct{
intvalor;
structELEMENTO*sig;
}ELEMENTO;
ELEMENTOn1,n2;
n1.sig=&n2;

Laasignacinquesehacecorrespondealafigura8.3

Figura8.3:Esquemadeunalistaligadacon2elementos.
Nota:SolamentesepuededeclararsigcomounapuntadortipoELEMENTO.Nosepuedetenerun
elementodeltipovariableyaqueestogeneraraunadefinicinrecursivalacualnoestapermitida.
Sepermiteponerunareferenciaaunapuntadoryaqueloslosbytessedejandeladoparacualquier
apuntador.

8.8Fallascomunesconapuntadores
Acontinuacinsemuestrandoserrorescomunesquesehacenconlosapuntadores.

Noasignarunapuntadoraunadireccindememoriaantesdeusarlo
int*x
*x=100;

loadecuadoser,tenerprimeramenteunalocalidadfsicadememoria,digamosinty;
int*x,y;
x=&y;
*x=100;

Indireccinnovlida
Supongamosquesetieneunafuncinllamadamalloc()lacualtratadeasignarmemoria
dinmicamente(entiempodeejecucin),lacualregresaunapuntadoralbloquedememoria
requeridasisepudoounapuntadoranuloenotrocaso.
char*malloc()unafuncindelabibliotecaestndarqueseverms
adelante.
Supongamosquesetieneunapuntadorchar*p
Considerar:
*p=(char*)malloc(100):/*pide100bytesdelamemoria*/
*p='y';

Existeunerrorenelcdigoanterior.Cules?
El*enlaprimeralneayaquemallocregresaunapuntadory*pnoapuntaaninguna
direccin.
Elcdigocorrectodeberser:
p=(char*)malloc(100);

Ahorasimallocnopuederegresarunbloquedememoria,entoncespesnulo,yporlo
tantonosepodrhacer:

*p='y';

UnbuenprogramaenCdeberevisarloanterior,porloqueelcdigoanteriorpuedeser
reescritocomo:
p=(char*)malloc(100):/*pide100bytesdelamemoria*/
if(p==NULL)
{
printf("Error:fueradememoria\n");
exit(1);
}
*p='y';

8.9Ejercicios
1. Escribirelprogramaqueordenalaslneasdeuntextoledodesdelaentradaestndar,donde
cadalneatienediferentelongitud,segnlodescritoenlaseccindearreglodeapuntadores.
2. Escribirunafuncinqueconviertaunacadenasaunnmerodepuntoflotanteusando
apuntadores.Considerarqueelnmerotieneelsiguienteformato99999999.999999,es
decir,nosedarennotacincientfica.Lafuncindebersuministrrseleunacadenay
deberdevolverunnmero.
3. Escribirunprogramaqueencuentreelnmerodevecesqueunapalabradada(estoes,una
cadenacorta)ocurreenunasentencia(unacadenalarga).
Leerlosdatosdelaentradaestndar.Laprimeralneaesunasolapalabra,enlasegunda
lneasetieneuntextogeneral.Leerambashastaencontraruncaracterdenuevalnea.
Recordarquesedebeinsertaruncaracternuloantesdeprocesar.
Lasalidatpicapodraser:
Lapalabraes"el"
Lasentenciaes"elperro,elgatoyelcanario"
Lapalabraocurrio3veces.

Subsecciones

9.1Usodemalloc,sizeof

y
free

calloc
9.2

y
realloc

9.3Listasligadas

9.4Programaderevisin

9.5Ejercicios

9.Asignacindinmicadememoriay
Estructurasdinmicas
LaasignacindinmicadememoriaesunacaractersticadeC.Lepermitealusuariocreartiposde
datosyestructurasdecualquiertamaodeacuerdoalasnecesidadesquesetenganenelprograma.
Serevisarndosdelasaplicacionesmscomunes:

Arreglosdinmicos
Estructurasdinmicasdedatos.

9.1Usodemalloc,sizeofyfree
Lafuncinmallocesempleadacomnmenteparaintentar``tomar''unaporcincontiguade
memoria.Estadefinidacomo:
void*malloc(size_tsize);

Loanteriorindicaqueregresarunapuntadordeltipovoid*,elcualeselinicioenmemoriade
laporcinreservadadetamaosize.Sinopuedereservaresacantidaddememorialafuncin
regresaunapuntadornulooNULL
Dadoquevoid*esregresado,Casumequeelapuntadorpuedeserconvertidoacualquiertipo.
Eltipodeargumentosize_testadefinidoenlacabecerastddef.hyesuntipoenterosin
signo.
Porlotanto:
char*cp;
cp=(char*)malloc(100);

intentaobtener100bytesyasignarlosaladireccindeinicioacp.

Esusualusarlafuncinsizeof()paraindicarelnmerodebytes,porejemplo:
int*ip;
ip=(int*)malloc(100*sizeof(int));

ElcompiladordeCrequierehacerunaconversindeltipo.Laformadelograrlacoercin(cast)es
usando(char*)y(int*),quepermiteconvertirunapuntadorvoidaunapuntadortipo
chareintrespectivamente.Hacerlaconversinaltipodeapuntadorcorrectoaseguraquela
aritmticaconelapuntadorfuncionardeformacorrecta.
Esunabuenaprcticausarsizeof()ansiseconoceeltamaoactualdeldatoqueserequiere,
yaquedeestaformaelcdigosehaceindependientedeldispositivo(portabilidad).
Lafuncinsizeof()puedeserusadaparaencontrareltamaodecualquiertipodedato,variable
oestructura.Simplementesedebeproporcionarunodelosanteriorescomoargumentoalafuncin.
Porlotanto:
inti;
structCOORD{floatx,y,z};
structCOORD*pt;
sizeof(int),sizeof(i),sizeof(structCOORD)y
sizeof(PT)sontambiensentenciascorrectas.

Enelsiguienteejemplosereservamemoriaparalavariableip,endondeseemplealarelacinque
existeentreapuntadoresyarreglos,paramanejarlamemoriareservadacomounarreglo.Por
ejemplo,sepuedenhacercosascomo:
main()
{
int*ip,i;
ip=(int*)malloc(100*sizeof(int));
ip[0]=1000;
for(i=0;i<100;++i)
scanf("%d",ip++);
}

Cuandosehaterminadodeusarunaporcindememoriasiempresedeberliberarusandola
funcinfree().Estafuncinpermitequelamemorialiberadaestedisponiblenuevementequizs
paraotrallamadadelafuncinmalloc()
Lafuncinfree()tomaunapuntadorcomounargumentoyliberalamemoriaalacualel
apuntadorhacereferencia.

9.2callocyrealloc
Existendosfuncionesadicionalesparareservarmemoria,calloc()yrealloc().Los
prototipossondadosacontinuacin:
void*calloc(size_tnmemb,size_tsize);
void*realloc(void*ptr,size_tsize);

Cuandoseusalafuncinmalloc()lamemorianoesinicializada(acero)oborrada.Sisequiere
inicializarlamemoriaentoncessepuedeusarlafuncincalloc.Lafuncincalloces
computacionalmenteunpocomscarapero,ocasionalmente,msconvenientequemalloc.Se
debeobservartambinladiferenciadesintaxisentrecallocymalloc,yaquecalloctomael
nmerodeelementosdeseados(nmemb)yeltamaodelelemento(size),comodosargumentos
individuales.
Porlotantoparaasignara100elementosenterosqueestninicializadosacerosepuedehacer:
int*ip;
ip=(int*)calloc(100,sizeof(int));

Lafuncinreallocintentacambiareltamaodeunbloquedememoriapreviamenteasignado.
Elnuevotamaopuedesermsgrandeomspequeo.Sielbloquesehacemsgrande,entoncesel
contenidoanteriorpermanecesincambiosylamemoriaesagregadaalfinaldelbloque.Siel
tamaosehacemspequeoentonceselcontenidosobrantepermanecesincambios.
Sieltamaodelbloqueoriginalnopuedeserredimensionado,entoncesreallocintentarasignar
unnuevobloquedememoriaycopiarelcontenidoanterior.Porlotanto,lafuncindevolverun
nuevoapuntador(odevalordiferentealanterior),estenuevovalorserelquedeberusarse.Sino
puedeserreasignadanuevamemorialafuncinreallocdevuelveNULL.
Siparaelejemploanterior,sequierereasignarlamemoriaa50enterosenvezde100apuntadospor
ip,sehar;
ip=(int*)realloc(ip,50*sizeof(int));

9.3Listasligadas
Regresandoalejemplodelcaptuloanteriorsedefinilaestructura:
typedefstruct{
intvalor;
structELEMENTO*sig;
}ELEMENTO;

Lacualpuedecrecerenformadinmica.
ELEMENTO*liga;

liga=(ELEMENTO*)malloc(sizeof(ELEMENT));/*Asignamemoriaparaliga*/
free(liga);/*liberalamemoriaasignadaalapuntadorligausandofree()*/

9.4Programaderevisin
Lacolaesunacoleccindeordenadadeelementosdelaquesepuedenborrarelementosenun
extremo(llamadoelfrentedelacola)oinsertarlosenelotro(llamadoelfinaldelacola.
Semuestraacontinuacinelcdigocompletoparamanipularestaestructura:
/*cola.c*/
/*DemodeestructurasdinamicasenC*/
#include<stdio.h>
#defineFALSO0
typedefstructnodo{
intdato;
structnodo*liga;
}elemento_lista;
voidMenu(int*opcion);
elemento_lista*AgregaDato(elemento_lista*apuntlista,intdato);
elemento_lista*BorrarDato(elemento_lista*apuntlista);
voidImprCola(elemento_lista*apuntlista);
voidLimpCola(elemento_lista*apuntlista);
main()
{
elemento_listalistmember,*apuntlista;
intdato,opcion;
apuntlista=NULL;
do{
Menu(&opcion);
switch(opcion){
case1:
printf("Ingresaundatoqueseraagregado");
scanf("%d",&dato);
apuntlista=AgregaDato(apuntlista,dato);
break;
case2:
if(apuntlista==NULL)
printf("Colavacia!\n");
else
apuntlista=BorrarDato(apuntlista);
break;
case3:
ImprCola(apuntlista);
break;
case4:
break;
default:
printf("Opcionnovalidaintentarnuevamente\n");
break;
}
}while(opcion!=4);

LimpCola(apuntlista);
}/*findemain*/
voidMenu(int*opcion)
{
charlocal;
printf("\nEntre\t1paraagregarundato,\n\t2paraborrarundato,\n\t3para
mostrarelcontenidodelacola\n\t4parasalir\n");
do{
local=getchar();
if((isdigit(local)==FALSO)&&(local!='\n'))
{
printf("\nSedebeingresarunentero.\n");
printf("Teclee1paraagregar,2paraborrar,3paraimprimir,4
parasalir\n");
}
}while(isdigit((unsignedchar)local)==FALSO);
*opcion=(int)local'0';
}
elemento_lista*AgregaDato(elemento_lista*apuntlista,intdato)
{
elemento_lista*lp=apuntlista;
if(apuntlista!=NULL){
while(apuntlista>liga!=NULL)
apuntlista=apuntlista>liga;
apuntlista>liga=(structnodo*)malloc(sizeof(elemento_lista));
apuntlista=apuntlista>liga;
apuntlista>liga=NULL;
apuntlista>dato=dato;
returnlp;
}
else
{
apuntlista=(structnodo*)malloc(sizeof(elemento_lista));
apuntlista>liga=NULL;
apuntlista>dato=dato;
returnapuntlista;
}
}
elemento_lista*BorrarDato(elemento_lista*apuntlista)
{
elemento_lista*tempp;
printf("Elelementoborradoes%d\n",apuntlista>dato);
tempp=apuntlista>liga;
free(apuntlista);
returntempp;
}
voidImprCola(elemento_lista*apuntlista)
{
if(apuntlista==NULL)
printf("Lacolaestavacia!!\n");
else
while(apuntlista!=NULL){
printf("%d\t",apuntlista>dato);
apuntlista=apuntlista>liga;
}
printf("\n");

}
voidLimpCola(elemento_lista*apuntlista)
{
while(apuntlista!=NULL){
apuntlista=BorrarDato(apuntlista);
}
}

9.5Ejercicios
1. Escribirunprogramaqueleaunnmero,queindicacuntosnmerosenterossern
guardadosenunarreglo,crearelarregloparaalmacenareltamaoexactodelosdatosy
entoncesleerlosenterosquesernguardadosenelarreglo.
2. Escribirunprogramaparaordenarunasecuenciadenmerosusandounrbolbinario.Un
rbolbinarioesunaestructuratiporbolconsolamente2(posibles)ramasdecadanodo.
Cadaramaentoncesrepresentaunadecisindefalsooverdadero.Paraordenarlosnmeros
simplementeasignaralaramaizquierdalosnmerosmenoresrespectoalnmerodelnodo,
yenlaramaderechaelresto(esdecir,losquesonmayoresoigualesa).
Porlotanto,silalistadeentradaes:1415497183516420170145,
sedebegenerarelrboldelafigura9.1.

Figura9.1:Arbolbinario.
Paraobtenerunalistaordenadaenformaascendente,recorrerelrbolenpreorden(depth
firstorder),esdecir,visitarlaraz,recorrerelsubrbolizquierdoenordenyrecorrerel
subrbolderechoenorden.Porloquelasalidadeberser:
Losvaloresordenadosson:
0344557914141516171820

Mostrar10valoresporlnea.

Subsecciones

10.1Apuntadoresaapuntadores

10.2Entradaenlalneadecomandos

10.3Apuntadoresafunciones

10.4Ejercicios

10.Tpicosavanzadosconapuntadores
Sehanrevisadovariasaplicacionesytcnicasqueusanapuntadoresenloscaptulosanteriores.As
mismosehanintroducidoalgunostemasavanzadosenelusodeapuntadores.Enestecaptulose
profundizanalgunostpicosqueyahansidomencionadosbrevementeyotrosquecompletanla
revisindeapuntadoresenC.
Enestecaptulosedesarrollalosiguiente:

Seexaminanapuntadoresaapuntadoresconmsdetalle.
Comoseusanlosapuntadoresenlalneadeentrada.
Yserevisanlosapuntadoresafunciones.

10.1Apuntadoresaapuntadores
Unarreglodeapuntadoreseslomismoqueapuntadoresaapuntadores.Elconceptodearreglosde
apuntadoresesdirectoyaqueelarreglomantienesusignificadoclaro.Sinembargo,sepueden
confundirlosapuntadoresaapuntadores.
Unapuntadoraunapuntadoresunaformadedireccionamientoindirectomltiple,ounacadenade
apuntadores.Comoseveenlafigura10.1,enelcasodeunapuntadornormal,elvalordel
apuntadoresladireccindelavariablequecontieneelvalordeseado.Enelcasodeunapuntadora
unapuntador,elprimerapuntadorcontieneladireccindelsegundoapuntador,queapuntaala
variablequecontieneelvalordeseado.
Sepuedellevardireccionamientoindirectomltipleacualquierextensindeseada,perohaypocos
casosdondemsdeunapuntadoraunapuntadorseanecesario,oinclusobuenodeusar.La
direccinindirectaenexcesoesdifcildeseguirypropensaaerroresconceptuales.
Sepuedetenerunapuntadoraotroapuntadordecualquiertipo.Considereelsiguientecdigo:
main()
{
charch;/*Uncaracter*/
char*pch;/*Unapuntadoracaracter*/
char**ppch;/*Unapuntadoraunapuntadoracaracter*/

ch='A';
pch=&ch;
ppch=&pch;
printf("%c\n",**ppch);/*muestraelvalordech*/
}

Loanteriorsepuedevisualizarcomosemuestraenlafigura10.1,endondeseobservaque**ppch
serefierealadireccindememoriade*pch,lacualasuvezserefierealadireccindememoria
delavariablech.Peroqusignificaloanteriorenlaprctica?

Figura10.1:Apuntadoraunapuntador,yapuntadoraunchar.
Sedeberecordarquechar*serefiereaunacadenalacualterminaconunnulo.Porlotanto,un
usocomnyconvenienteesdeclararunapuntadoraunapuntador,yelapuntadoraunacadena,ver
figura10.2.

Figura10.2:Apuntadoraunapuntador,yapuntadoraunacadena.
Tomandounpasomsallloanterior,sepuedentenervariascadenasapuntadasporelapuntador,
verfigura10.3

Figura10.3:Apuntadoravariascadenas.
Sepuedenhacerreferenciasacadenasindividualesmedianteppch[0],ppch[1],....Estoes
idnticoahaberdeclaradochar*ppch[].
Unaaplicacincomndeloanterioresenlosargumentosdelalneadecomandosqueserevisarn
acontinuacin.

10.2Entradaenlalneadecomandos
Cpermiteleerargumentosenlalneadecomandos,loscualespuedenserusadosenlosprogramas.
Losargumentossondadosotecleadosdespusdelnombredelprogramaalmomentodeser
ejecutadoelprograma.
Loanteriorsehavistoalmomentodecompilar,porejemplo:
gccoprogprog.c

dondegcceselcompiladoryoprogprog.csonlosargumentos.
Parapoderusarlosargumentosenelcdigosedebedefinircomosiguelafuncinmain.
main(intargc,char**argv)

o
main(intargc,char*argv[])

Conloquelafuncinprincipaltieneahorasuspropiosargumentos.Estossonsolamentelosnicos
argumentosquelafuncinmainacepta.
*
argceselnmerodeargumentosdadosincluyendoelnombredelprograma.
*
argvesunarreglodecadenasquetieneacadaunodelosargumentosdelalneade
comandosincluyendoelnombredelprogramaenelprimerelementodelarreglo.
Semuestraacontinuacinunprogramadeejemplo:
main(intargc,char**argv)
{
/*Esteprogramamuestralosargumentosdelalineadecomandos*/
inti;
printf("argc=%d\n\n",argc);
for(i=0;i<argc;++i)
printf("\t\targv[%d]:%s\n",i,argv[i]);
}

Suponiendoquesecompilayseejecutaconlossiguientesargumentos:
argsf1"f2yf3"f45FIN

Lasalidaser:
argc=6
argv[0]:args
argv[1]:f1
argv[2]:f2yf3
argv[3]:f4

argv[4]:5
argv[5]:FIN

Observarlosiguiente:

argv[0]contieneelnombredelprograma.
argccuentaelnmerodeargumentosincluyendoelnombredelprograma.
Losespaciosenblancodelimitanelfindelosargumentos.
Lascomillasdobles""sonignoradasysonusadasparaincluirespaciosdentrodeun
argumento.

10.3Apuntadoresafunciones
LosapuntadoresafuncionessonquizunodelosusosmsconfusosdelosapuntadoresenC.Los
apuntadoresafuncionesnosontancomunescomootrosusosquetienenlosapuntadores.Sin
embargo,unusocomnescuandosepasanapuntadoresafuncionescomoparmetrosenlallamada
aunafuncin.
Loanterioresespecialmentetilcuandosedebenusardistintasfuncionesquizspararealizartareas
similaresconlosdatos.Porejemplo,sepuedenpasarlosdatosylafuncinqueserusadapor
algunafuncindecontrol.ComosevermsadelantelabibliotecaestndardeCdafuncionespara
ordenamiento(qsort)ypararealizarbsqueda(bsearch),alascualesselespuedenpasarfunciones.
Paradeclararunapuntadoraunafuncinsedebehacer:
int(*pf)();

Locualdeclaraunapuntadorpfaunafuncinqueregresauntipodedatoint.Todavanoseha
indicadoaquefuncinapunta.
Suponiendoquesetieneunafuncinintf(),entoncessimplementesedebeescribir:
pf=&f;

paraque

apuntealafuncin

Paraquetrabajeenformacompletaelcompiladoresconvenientequesetenganlosprototipos
completosdelasfuncionesylosapuntadoresalasfunciones,porejemplo:
intf(int);
int(*pf)(int)=&f;

Ahoraf()regresaunenteroytomaunenterocomoparmetro.
Sepuedenhacercosascomo:

ans=f(5);
ans=pf(5);

loscualessonequivalentes.
Lafuncindelabibliotecaestndarqsortesmuytilyestadiseadaparaordenarunarreglo
usandounvalorcomollavedecualquiertipoparaordenarenformaascendente.
Elprototipodelafuncinqsortdelabibliotecastdlib.hes:
voidqsort(void*base,size_tnmiemb,size_ttam,
int(*compar)(constvoid*,constvoid*));

Elargumentobaseapuntaalcomienzodelvectorqueserordenado,nmiembindicaeltamao
delarreglo,tameseltamaoenbytesdecadaelementodelarregloyelargumentofinalcompar
esunapuntadoraunafuncin.
Lafuncinqsortllamaalafuncincomparlacualesdefinidaporelusuarioparacompararlos
datoscuandoseordenen.Observarqueqsortconservasuindependenciarespectoaltipodedato
aldejarlelaresponsabilidadalusuario.Lafuncincompardeberegresarundeterminadovalor
enterodeacuerdoalresultadodecomparacin,quedebeser:
menorquecero:sielprimervaloresmenorqueelsegundo.
cero:sielprimervaloresigualqueelsegundo.
mayorquecero:sielprimervaloresmayorqueelsegundo.
Acontinuacinsemuestraunejemploqueordenaunarreglodecaracteres,observarqueenla
funcincomp,sehaceuncastparaforzareltipovoid*altipochar*.
#include<stdlib.h>
intcomp(constvoid*i,constvoid*j);
main()
{
inti;
charcad[]="facultaddecienciasfisicomatematicas";

printf("\n\nArreglooriginal:\n");
for(i=0;i<strlen(cad);i++)
printf("%c",cad[i]);
qsort(cad,strlen(cad),sizeof(char),comp);
printf("\n\nArregloordenado:\n");
for(i=0;i<strlen(cad);i++)
printf("%c",cad[i]);
printf("\n");
}
intcomp(constvoid*i,constvoid*j)
{
char*a,*b;

a=(char*)i;/*Paraforzarvoid*altipochar*,sehacecast*/
b=(char*)j;/*empleando(char*)*/
return*a*b;
}

10.4Ejercicios
1. Escribirunprogramaquemuestrelasltimaslneasdeuntextodeentrada.Pordefectoo
``default''ndeberser7,peroelprogramadeberpermitirunargumentoopcionaltalque
ultlinn
muestralasltimasnlneas,dondenesunentero.Elprogramadeberhacerelmejoruso
delespaciodealmacenamiento.(Eltextodeentradapodrserledodeunarchivodado
desdelalneadecomandosoleyendounarchivodelaentradaestndar.)
2. Escribirunprogramaqueordeneunalistadeenterosenformaascendente.Sinembargo,si
unaopcinrestapresenteenlalneadecomandoselprogramadeberordenarlalistaen
formadescendente.
3. Escribirunprogramaquelealasiguienteestructurayordenelosdatosporlallaveusando
qsort
typedefstruct{
charllave[10];
intalgo_mas;
}Record;

Subsecciones

11.1Operadoressobrebits

11.2Camposdebit

11.2.1Portabilidad

11.3Ejercicios

11.Operadoresdebajonivelycamposdebit
Sehavistocomolosapuntadoresnosdancontrolsobrelasoperacionesdebajoniveldelamemoria.
Muchosprogramas(porejemplo,aplicacionesdeltiposistemas)operanactualmenteabajonivel
dondebitsindividualesdebensermanipulados.
LacombinacindeapuntadoresyoperadoresanivelbithacendeCtilparamuchasaplicaciones
debajonivelypuedencasireemplazaralcdigoensamblador.(Solamenteun10%
aproximadamentedeUNIXestaencdigoensambladorelrestoesC.)

11.1Operadoressobrebits
LosoperadoressobrebitsdeCseresumenenlasiguientetabla:
Operador

Accin

&

Oexclusiva(XOR)

Complementoauno

Negacin

<<

Desplazamientoalaizquierda

>>

Desplazamientoaladerecha

Nosedebeconfundireloperador&coneloperador&&:&eseloperadorYsobrebits,&&esel
operadorlgicoY.Similarmentelosoperadores|y||.
Eloperadorunario~slorequiereunargumentoaladerechadeloperador.
Losoperadoresdedesplazamiento,>>y<<,mueventodoslosbitsenunaposicinhacialaderecha
olaizquierdaundeterminadonmerodeposiciones.Elformatogeneraldelasentenciade
desplazamientoaladerechaes:

variable>>num_pos_de_bit

yelformatogeneraldedesplazamientoalaizquierdaes
variable<<num_pos_de_bit

Comolosoperadoresdesplazanbitsenunsentido,lacomputadoratraecerosenelotroextremo.Se
deberecordarqueundesplazamientonoesunarotacin:losbitsdesplazadosenunextremono
vuelvenalotro.Sepierdenyloscerostradoslosreemplazan.
Unaaplicacinquetienenlosoperadoresdedesplazamientodebitsespararealizarmultiplicaciones
ydivisionesrpidasconenteros.Comoseveenlasiguientetabla,dondeundesplazamientoala
izquierdaesmultiplicarpor2yunoaladerechadividirpor2.
charx

Ejecucin

Valordex

x=7;

00000111

x<<1;

00001110

14

x<<3;

01110000

112

x<<2;

11000000

192

x>>1;

01100000

96

x>>2;

00011000

24

Losdesplazamientossonmuchomsrpidosquelamultiplicacinactual(*)oladivisin(/)por
dos.Porlotanto,sisequierenmultiplicacionesodivisionesrpidaspor2usedesplazamientos.
Conlafinalidaddeilustraralgunospuntosdelosoperadoressobrebits,semuestralasiguiente
funcincontbit,lacualcuentalosbitspuestosa1enunnmerode8bits(unsignedchar)
pasadocomounargumentoalafuncin.
intcontbit(unsignedcharx)
{
intcount;
for(count=0;x!=0;x>>=1)
if(x&1)
count++;
returncount;
}

EnestafuncinseilustranvariascaractersticasdeC:

Elciclofornoesusadoparasimplementecontar.
x>>=1esequivalenteax=x>>1.
Elcicloforiterativamentedesplazaaladerechaxhastaquexsehace0.
x&01enmascaraelprimerbitdex,ysiestees1entoncesincrementacount.

11.2Camposdebit
Alcontrariodelamayoradeloslenguajesdeprogramacin,Ctieneunmtodopredefinidopara
accederaunnicobitenunbyte.Estemtodopuedeserutilsimoporunaseriederazones:

Sielalmacenamientoeslimitado,sepuedenalmacenarvariasvariablesbooleanasenunbyte;
ciertasinterfacesdedispositivotransmiteninformacinquesecodificaenbitsdentrodeun
byte;
ciertasrutinasdeencriptacinnecesitanaccederalosbitsenunbyte.

ElmtodoqueCusaparaaccederalosbitssebasaenlaestructura.Uncampodebitesuntipo
especialdeestructuraquedefinelalongitudenbitsquetendrcadaelemento.Elformatogeneralde
unadefinicindecampodebites:
structnomb_estruct{
tiponombre_1:longitud;
tiponombre_2:longitud;
.
.
.
tiponombre_n:longitud;
}
Sedebedeclararuncampodebitcomoint,unsignedosigned.Sedebedeclararloscamposdebits
delongitud1comounsigned,yaqueunbitniconopuedetenersigno.
Porejemplo,considerarestadefinicindeestructura:
structempaquetado{
unsignedintb1:1;
unsignedintb2:1;
unsignedintb3:1;
unsignedintb4:1;
unsignedinttipo:4;
unsignedintent_raro:9;
}paquete;

Laestructuraempaquetadocontiene6miembros:4banderasde1bit(b1,b2,b3yb4),unode4
bits(tipo)yotrode9bits(ent_raro).
Cautomticamenteempacaloscamposdebitanteriorestancompactamentecomoseaposible,
dondelalongitudmximadelcampoesmenorqueoigualalalongituddelapalabraenteradela
computadora.Sinofueraelcaso,entoncesalgunoscompiladorespodranpermitirtraslapeen
memoriaparaloscampos,mientrasotrospodranguardarelsiguientecampoenlasiguiente
palabra.

Laformadeaccesarlosmiembrosesenlaformausual:
paquete.tipo=7;

Conestructuraanteriorsetieneque:

Solamentelosnbitsmsbajossonasignadosaunnmerodenbits.Porlotanto,elcampo
tiponopuedetomarvaloresmayoresque15,yaqueesde4bitsdelargo.
Loscamposdebitsonsiempreconvertidosauntipoenterocuandosehacealgnclculo
conellos.
Sepermitemezclarlostipos``normales''conloscamposdebit.

11.2.1Portabilidad
Loscamposdebitsonunaformaconvenientedeexpresarmuchasoperacionesdificiles.Sin
embargo,loscamposdebitcarecendeportabilidadentreplataformas,poralgunadelassiguientes
razones:

Losenterospodranserconosinsigno.
Muchoscompiladoreslimitanelnmeromximodebitsenelcampodebitaltamaodeun
integer,elcualpodraserde16bitsode32bits.
Algunosmiembroscamposdebitsonguardadosdeizquierdaaderecha,otrossonguardados
dederechaaizquierdaenmemoria.
Siloscamposdebitssonmuylargos,elsiguientecampodebitpodraserguardado
consecutivamenteenmemoria(traslapandoloslmitesentrelaslocalidadesdememoria)o
enlasiguientepalabradememoria.

11.3Ejercicios
1. Escribirunafuncinquemuestreunnmerode8bits(unsignedchar)enformatobinario.
2. Escribirunafuncinponerbits(x,p,n,y)queregresex,connbitsqueempiezanen
laposicinpyestanaladerechadeunavariableyunsignedchar,dejndolosenxenla
posicinpyalaizquierdadejandolosotrosbitssincambio.
Porejemplo,six=10101010(170decimal),y=10100111(167
decimal),n=3yp=6,entoncessenecesitatomar3bitsdedey(111)yponerlosen
xenlaposicin10xxx010paraobtenerlarespuesta10111010.
Larespuestadebermostrarseenformabinaria(verprimerejercicio),sinembargola
entradapuedeserenformadecimal.
Lasalidapodrasercomolasiguiente:
x=10101010(binario)
y=10100111(binario)
ponerbitsn=3,p=6dax=10111010(binario)

3. Escribirunafuncinqueinviertalosbitsdex(unsignedchar)yguardelarespuestaeny.
Larespuestadebermostrarseenformabinaria(verprimerejercicio),sinembargola
entradapuedeestarenformadecimal.
Lasalidapodrasercomolasiguiente:
x=10101010(binario)
xinvertida=01010101(binario)

4. Escribirunafuncinquerote(nodesplaze)aladerechanposicionesdebitsdexdeltipo
unsignedchar.Larespuestadebermostrarseenformabinaria(verprimerejercicio)yla
entradapuedeserenformadecimal.
Lasalidapodrasercomolasiguiente:
x=10100111(binario)
xrotadapor3=11110100(binario)

Subsecciones

12.1Directivasdelpreprocesador
12.1.1

#define

12.1.2

#undef

12.1.3

#include

12.1.4

#if
Inclusincondicional

12.2Controldelpreprocesadordelcompilador

12.3Otrasdirectivasdelpreprocesador

12.4Ejercicios

12.ElpreprocesadordeC
12.1Directivasdelpreprocesador
Comosecomentoenelprimercaptuloelpreprocesamientoeselprimerpasoenlatapade
compilacindeunprogramaestapropiedadesnicadelcompiladordeC.
Elpreprocesadortienemsomenossupropiolenguajeelcualpuedeserunaherrramientamuy
poderosaparaelprogramador.Todaslasdirectivasdepreprocesadorocomandosinicianconun#.
Lasventajasquetieneusarelpreprocesadorson:

losprogramassonmsfcilesdedesarrollar,
sonmsfcilesdeleer,
sonmsfcilesdemodificar
yelcdigodeCesmstransportableentrediferentesarquitecturasdemquinas.

12.1.1#define
Elpreprocesadortambinpermiteconfigurarellenguaje.Porejemplo,paracambiaralassentencias
debloquedecdigo{...}delimitadoresquehayainventadoelprogramadorcomoinicio
...finsepuedehacer:
#defineinicio{
#definefin}

Durantelacompilacintodaslasocurrenciasdeinicioyfinsernreemplazadasporsu
correspondiente{o}delimitadorylassiguientestapasdecompilacindeCnoencontrarn
ningunadiferencia.
Ladirectiva#defineseusaparadefinirconstantesocualquiersustitucindemacro.Suformato
eselsiguiente:
#define<nombredemacro><nombredereemplazo>
Porejemplo:
#defineFALSO0
#defineVERDADERO!FALSO

Ladirectiva#definetieneotrapoderosacaracterstica:elnombredemacropuedetener
argumentos.Cadavezqueelcompiladorencuentraelnombredemacro,losargumentosreales
encontradosenelprogramareemplazanlosargumentosasociadosconelnombredelamacro.Por
ejemplo:
#defineMIN(a,b)(a<b)?a:b
main()
{
intx=10,y=20;
printf("ELminimoes%d\n",MIN(x,y));
}

Cuandosecompilaesteprograma,elcompiladorsustiuirlaexpresindefinidaporMIN(x,y),
exceptoquexeysernusadoscomolosoperandos.Asdespusdequeelcompiladorhacela
sustitucin,lasentenciaprintfsersta:
printf("Elminimoes%d\n",(x<y)?x:y);

ComosepuedeobservardondesecoloqueMIN,eltextoserreemplazadoporladefinicin
apropiada.Porlotanto,sienelcdigosehubierapuestoalgocomo:
x=MIN(q+r,s+t);

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

Otrosejemplosusando#definepuedenser:
#defineDeg_a_Rad(X)(X*M_PI/180.0)
/*Conviertegradossexagesimalesaradianes,M_PIeselvalordepi*/
/*yestadefinidaenlabibliotecamath.h*/
#defineIZQ_DESP_8<<8

LaltimamacroIZQ_DESP_8essolamentevlidaentantoelreemplazodelcontextoesvlido,
porejemplo:x=yIZQ_DESP_8.
Elusodelasustitucindemacrosenellugardelasfuncionesrealestieneunbeneficioimportante:

incrementalavelocidaddelcdigoporquenosepenalizaconunallamadadefuncin.Sinembargo,
sepagaesteincrementodevelocidadconunincrementoeneltamaodelprogramaporquese
duplicaelcdigo.

12.1.2#undef
Seusa#undefparaquitarunadefinicindenombredemacroquesehayadefinidopreviamente.
Elformatogenerales:
#undef<nombredemacro>
Elusoprincipalde#undefespermitirlocalizarlosnombresdemacrossloenlasseccionesde
cdigoquelosnecesiten.

12.1.3#include
Ladirectivadelpreprocesador#includeinstruyealcompiladorparaincluirotroarchivofuenteque
estadadoconestadirectivaydeestaformacompilarotroarchivofuente.Elarchivofuentequese
leersedebeencerrarentrecomillasdoblesoparntesisdengulo.Porejemplo:
#include<archivo>
#include"archivo"

Cuandoseindica<archivo>seledicealcompiladorquebusquedondeestanlosarchivos
incluidoso``include''delsistema.UsualmentelossistemasconUNIXguardanlosarchivosenel
directorio/usr/include.
Siseusalaforma"archivo"esbuscadoeneldirectorioactual,esdecir,dondeelprogramaesta
siendoejecutado.
Losarchivosincluidosusualmentecontienenlosprototiposdelasfuncionesylasdeclaracionesde
losarchivoscabecera(headerfiles)ynotienencdigodeC(algoritmos).

12.1.4#ifInclusincondicional
Ladirectiva#ifevaluaunaexpresinconstanteentera.Siempresedebeterminarcon#endif
paradelimitirelfindeestasentencia.
Sepuedenasmismoevaluarotrocdigoencasosecumplaotracondicin,obien,cuandonose
cumpleningunausando#elifo#elserespectivamente.
Porejemplo,
#defineMEX0
#defineEUA1
#defineFRAN2

#definePAIS_ACTIVOMEX
#ifPAIS_ACTIVO==MEX
charmoneda[]="pesos";
#elifPAIS_ACTIVO==EUA
charmoneda[]="dolar";
#else
charmoneda[]="franco";
#endif

Otromtododecompilacincondicionalusalasdirectivas#ifdef(sidefinido)y#ifndef(sino
definido).
Elformatogeneralde#ifdefes:
#ifdef<nombredemacro>
<secuenciadesentecias>
#endif
Sielnombredemacrohasidodefinidoenunasentencia#define,secompilarlasecuenciade
senteciasentreel#ifdefy#endif.
Elformatogeneralde#ifdefes:
#ifndef<nombredemacro>
<secuenciadesentecias>
#endif
Lasdirectivasanterioressontilespararevisarsilasmacrosestndefinidastalvezpormdulos
diferentesoarchivosdecabecera.
Porejemplo,paraponereltamaodeunenteroparaunprogramaportableentreTurboCdeDOSy
unsistemaoperativoconUNIX,sabiendoqueTurboCusaenterosde16bitsyUNIXenterosde32
bits,entoncessisequierecompilarparaTurboCsepuededefinirunamacroTURBOC,lacualser
usadadelasiguienteforma:
#ifdefTURBOC
#defineINT_SIZE16
#else
#defineINT_SIZE32
#endif

12.2Controldelpreprocesadordelcompilador
Sepuedeusarelcompiladorgccparacontrolarlosvaloresdadosodefinidosenlalneade
comandos.Estopermitealgunaflexibilidadparaconfigurarvaloresademasdeteneralgunasotras
funcionestiles.Paraloanterior,seusalaopcinDmacro[=defn],porejemplo:
gccDLONGLINEA=80prog.coprog

quehubiesetenidoelmismoresultadoque
#defineLONGLINEA80

encasodequehubieradentrodelprograma(prog.c)algn#defineo#undefpasarapor
encimadelaentradadelalneadecomandos,yelcompiladorpodramandarun``warning''sobre
estasituacin.
Tambinsepuedeponerunsmbolosinvalor,porejemplo:
gccDDEBUGprog.coprog

Endondeelvalorquesetomaesde1paraestamacro.
Lasaplicacionespuedenserdiversas,comoporejemplocuandosequierecomounabanderapara
depuracinsepuedehaceralgocomolosiguiente:
#ifdefDEBUG
printf("Depurando:Versindelprograma1.0\n");
#else
printf("Versiondelprograma1.0(Estable)\n");
#endif

Comoloscomandosdelpreprocesadorpuedenestarencualquierpartedeunprograma,sepueden
filtrarvariablesparamostrarsuvalor,cuandoseestadepurando,verelsiguienteejemplo:
x=y*3;
#ifdefDEBUG
printf("Depurando:variablesxeyigualesa\n",x,y);
#endif

LaopcinEhacequelacompilacinsedetengadespusdelatapadepreprocesamiento,porlo
anteriornoseestapropiamentecompilandoelprograma.Lasalidadelpreprocesamientoesenviada
alaentradaestndar.GCCignoralosarchivosdeentradaquenorequieranpreprocesamiento.

12.3Otrasdirectivasdelpreprocesador
Ladirectiva#errorforzaalcompiladorapararlacompilacincuandolaencuentra.Seusa
principalmenteparadepuracin.Porejemplo:
#ifdefOS_MSDOS
#include<msdos.h>
#elifdefOS_UNIX
#include"default.h"
#else
#errorSistemaOperativoincorrecto
#endif

Ladirectiva#linenmero``cadena''informaalpreprocesadorcualeselnmerosiguientedela
lneadeentrada.Cadenaesopcionalynombralasiguientelneadeentrada.Estoesusado
frecuentementecuandosontraducidosotroslenguajesaC.Porejemplo,losmensajesdeerror
producidosporelcompiladordeCpuedenreferenciarelnombredelarchivoylalneadelafuente

originalenvezdelosarchivosintermediosdeC.
Porejemplo,losiguienteespecificaqueelcontadordelneaempezarcon100.
#line100"test.c"/*inicializaelcontadordelineaynombredearchivo*/
main()/*linea100*/
{
printf("%d\n",__LINE__);/*macropredefinida,linea102*/
printf("%s\n",__FILE__);/*macropredefinidaparaelnombre*/
}

12.4Ejercicios
1. Definirunamacromin(a,b)paradeterminarelenteromspequeo.Definirotramacro
min3(a,b,c)entrminosdemin(a,b).Incorporarlasmacrosenunprograma
demostrativoendondesepidaalusuariotresnmerosysemuestreelmspequeo.
2. Definirunnombredemacrodepreprocesadorparaseleccionar:
losbitsmenossignificativosdeuntipodedatounsignedchar.
elnsimobit(asumiendoqueelmenossignificativoes0)deuntipodedato
unsignedchar.

Subsecciones

13.1VentajasdelusarUNIXconC

13.2Usodefuncionesdebibliotecasyllamadasdelsistema

13.C,UNIXylasbibliotecasestndar
ExisteunarelacinestrechaentreCyelsistemaoperativoqueejecutalosprogramasdeC.El
sistemaoperativoUNIXestaescritoensumayorparteconC.EnestecaptulosevercomoCy
UNIXinteractunjuntos.
SeusaUNIXparamanejarelespaciodelarchivo,paraeditar,compilaroejecutarprogramas,entre
otrascosas.
SinembargoUNIXesmuchomstilqueloanterior.

13.1VentajasdelusarUNIXconC

PortabilidadUnixoalgunavariantedeUNIXestndisponiblesenmuchasmquinas.Los
programasescritosconUNIXyCestndaresdebencorrerencualquiermquina
prcticamentesinningnproblema.
Multiusuario/MultitareaMuchosprogramaspuedencompartirlacapacidadde
procesamientodelasmquinas.
ManejodearchivosElsistemajerrquicodearchivosempleamuchasrutinasdemanejode
archivos.
ProgramacindelShellUNIXsuministraunintrpretedecomandospoderosoqueentiende
masde200comandosyquepuedetambincorrerUNIXoprogramasdelusuario.
EntubamientooPipePermitelaconexinentreprogramas,endondelasalidadeun
programapuedeserlaentradadeotro.Loanteriorpuedehacercedesdelalneadecomandos
odentrodeunprogramadeC.
UtilerasdeUNIXHaycercade200utilerasquepermitenejecutarmuchasrutinassin
escribirnuevosprogramas.Porejemplo:make,grepdiff,awk,etc.
LlamadasalsistemaUNIXtieneaproximadamente60llamadasalsistema,quesonel
corazndelsistemaoperativoodelkerneldeUNIX.Lasllamadasestnactualmenteescritas
enC.TodasellaspuedenseraccesadasdesdeprogramasdeC.Ejemplosdeestassonel
sistemabsicodeE/S,accesoalrelojdelsistema.Lafuncinopen()esunejemplodeuna
llamadaalsistema.
BibliotecadefuncionesQuesonadicionesalsistemaoperativo.

13.2Usodefuncionesdebibliotecasyllamadas
delsistema
ParausarlasbibliotecasdefuncionesylasllamadasalsistemaenunprogramadeCsimplementese
debellamarlafuncinapropiadadeC.
EjemplosdelasfuncionesdelabibliotecaestndarquehansidovistassonlasfuncionesdeE/Sde
altonivelfprintf(),malloc(),...
Operadoresaritmticos,generadoresdenmerosaleatoriosrandom(),srandom(),lrand48(),
drand48(),etc.yfuncionesparaconversindecadenasalostiposbsicosdeC(atoi(),atof(),etc.)
sonmiembrosdelabibliotecaestndarstdlib.h.
Todaslasfuncionesmatemticascomosin(),cos(),sqrt()sonfuncionesdelabiblioteca
estndardematemticas(math.h).
Paramuchasllamadasdelsistemayfuncionesdelasbibliotecassetienequeincluirelarchivo
cabeceraapropiado,porejemplo:stdio.h,math.h.
Parausarunafuncinsedebeasegurardehaberpuestoloscorrespondientes#includeenel
archivodeC.Deestaformalafuncinpuedeserllamadacorrectamente.
Esimportanteasegurarsequelosargumentostenganlostiposesperados,deotraformalafuncin
probablementeproducirresultadosextraos.
Algunasbibliotecasrequierenopcionesextrasantesdequeelcompiladorpuedasoportarsuuso.Por
ejemplo,paracompilarunprogramaqueincluyafuncionesdelabibliotecamath.helcomando
podraserdelasiguienteforma:
gccmatprog.comatprog.clm

Laopcinfinallmesunainstruccinparaligarlabibliotecamatemticaconelprograma.La
pginademanparacadafuncinusualmenteinformasiserequierealgunabanderadecompilacin
especial.
Informacindecasitodaslasllamadasalsistemayfuncionesdebibliotecaestndisponiblesenlas
pginasdelman.Seencuentrandisponiblesenlneacontansloteclearmanyelnombredela
funcin.Porejemplo:
mandrand48

nosdarinformacinacercadestegeneradordenmerosaleatorios.

Subsecciones

14.1Funcionesaritmticas

14.2Nmerosaleatorios

14.3Conversindecadenas

14.4Bsquedayordenamiento

14.5Ejercicios

14.Biblioteca<stdlib.h>
Parausartodaslasfuncionesdestabibliotecasedebetenerlasiguientedirectiva
#include<stdlib.h>

Lasfuncionesdelabibliotecapuedenseragrupadasentrescategorasbsicas:

Aritmticas;
Nmerosaleatorios;y
Conversindecadenas.

Elusodetodaslasfuncionesessencillo.Seconsiderandentrodelcaptuloenformabreve.

14.1Funcionesaritmticas
Haycuatrofuncionesenterasbsicas:
intabs(intj);
longintlabs(longintj);
div_tdiv(intnumer,intdenom);
ldiv_tldiv(longintnumer,longintdenom);

Fundamentalmentehaydosfuncionesparaenterosyparacompatibilidadconenteroslargos.

abs()Lafuncinregresaelvalorabsolutodelargumentoenteroj.
div()Calculaelvalornumerentredenomydevuelveelcocienteyelrestoenuna
estructurallamadadiv_tquecontienedosmiembrosllamadosquotyrem.

Laestructuradiv_testadefinidaenstdlib.hcomosigue:
typedefstruct{
intquot;/*cociente*/
intrem;/*residuo*/
}div_t;

Laestructuraldiv_tesdefinidadeunaformasimilar.

Semuestraunejemplodondesehaceusodelafuncindiv_t:
#include<stdlib.h>
main()
{
intnum=8,den=3;
div_tres;
res=div(num,den);
printf("Respuesta:\n\tCociente=%d\n\tResiduo=%d\n",
res.quot,res.rem);
}

quegeneralasiguientesalida:
Respuesta:
Cociente=2
Residuo=2

14.2Nmerosaleatorios
Losnmerosaleatoriossontilesenprogramasquenecesitansimulareventosaleatorios,tales
comojuegos,simulacionesyexperimentos.Enlaprcticaningunafuncinproducedatosaleatorios
verdaderoslasfuncionesproducennmerospseudoaleatorios.Losnmerosaleatoriosson
calculadosapartirdeunafrmuladada(losdistintosgeneradoresusandiferentesfrmulas)ylas
secuenciasdenmerosquesonproducidasserepiten.Unasemilla(seed)esusualmenteinicializada
paraquelasecuenciaseagenerada.Porlotanto,silasemillaessiempreinicializadaconelmismo
valortodoeltiempo,elmismoconjuntosersiemprecalculado.
Unatcnicacomnparaintroducirmsaleatoriedadenelgeneradordenmerosaleatorioses
usandoeltiempoylafechaparainicializarlasemilla,yaquestesiempreestarcambiando.
Haymuchasfuncionesdenmeros(pseudo)aleatoriosenlabibliotecaestndar.Todasellasoperan
conlamismaideabsicaperogeneransecuenciasdiferentesdenmeros(basadasenfunciones
generadorasdiferentes)sobrerangosdiferentesdenmeros.
Elconjuntomssimpledefuncioneses:
intrand(void);
voidsrand(unsignedintsemilla);

rand()Lafuncindevuelveunenteropseudoaleatorioentre0y

(RAND_MAX).

srand()Establecesuargumentocomolasemilladeunanuevaseriedeenterospseudo
aleatorios.

Unejemplosencillodelusodeltiempodelafechaesinicializandolasemillaatravsdeuna
llamada:
srand((unsignedint)time(NULL));

Elsiguienteprogramatarjeta.cmuestraelusodeestasfuncionesparasimularunpaquetede
tarjetasqueestasiendorevueltas.
/*
**Seusannumerosaleatoriospararevolverlas"tarjetas"delabaraja.
**Elsegundoargumentodelafuncionindicaelnumerodetarjetas.
**Laprimeravezqueestafuncionesllamada,srandes
**llamadaparainicializarelgeneradordenumerosaleatorios.
*/
#include<stdlib.h>
#include<time.h>
#defineVERDADERO1
#defineFALSO0
voidintercambiar(int*baraja,intn_cartas)
{
inti;
staticintprimera_vez=VERDADERO;
/*
**Inicializarelgeneradordenumerosconlafechaactual
**siaunnosehahecho.
*/
if(primera_vez){
primera_vez=FALSO;
srand((unsignedint)time(NULL));
}
/*
**"intercambiar"empleandoparesdecartas.
*/
for(i=n_cartas1;i>0;i=1){
intalguno;
inttemp;
alguno=rand()%i;
temp=baraja[alguno];
baraja[alguno]=baraja[i];
baraja[i]=temp;
}
}

14.3Conversindecadenas
Existenunascuantasfuncionesparaconvertircadenasaenteros,enteroslargosyvaloresflotantes.
Estasson:

doubleatof(constchar*cadena)Convierteunacadenaaunvalorflotante.
intatoi(constchar*cadena)Convierteunacadenaaunvalorentero.
intatol(constchar*cadena)Convierteunacadenaaunvalorenterolargo.
doublestrtod(constchar*cadena,char**finap)Convierteunacadenaaunvalorde
puntoflotante.
doublestrtol(constchar*cadena,char*finap,intbase)Convierteunacadenaaunentero
largodeacuerdoaunabasedada,lacualdeberestarentre2y36inclusive.
unsignedlongstrtoul(constchar*cadena,char*finap,intbase)Convierteunacadenaa
unenterolargosinsigno.

Variasdelasfuncionessepuedenusarenformadirecta,porejemplo:
char*cad1="100";
char*cad2="55.444";
char*cad3="1234";
char*cad4="123cuatro";
char*cad5="invalido123";
char*cad6="123E23Hola";
char*cad7;
inti;
floatf:
i=atoi(cad1);/*i=100*/
f=atof(cad2);/*f=55.44*/
i=atoi(cad3);/*i=1234*/
i=atoi(cad4);/*i=123*/
i=atoi(cad5);/*i=0*/
f=strtod(cad6,&cad7);/*f=1.230000E+25ycad7=hola*/

Nota:

Loscaracteresenblancosonsaltados.
Caracteresilegalessonignorados.
Silaconversinnopuedeserhechaseregresaceroyerrnoespuestaconelvalor
ERANGE.

14.4Bsquedayordenamiento
Labibliotecastdlib.htienedosfuncionestilesparahacerbsquedayordenamientodedatos
decualquiertipo.Lafuncinqsort()yafuevistapreviamenteenlaseccin10.3.
Paracompletarlalistaseanotaelprototipo,peroparaverunejemplopasaralcaptuloindicado.
Lafuncinqsortdelabibliotecaestndaresmuytil,yaqueestadiseadaparaordenarun
arregloporunvalorllavedecualquiertipoenordenascendente,contaldequeloselementosdel
arregloseandeuntipofijo.
Elprototipodelafuncindeacuerdoastdlib.hes:
voidqsort(void*base,size_tnmiemb,size_ttam,
int(*compar)(constvoid*,constvoid*));

Similarmente,hayunafuncinparabsquedabinaria,bsearch()lacualtieneelsiguiente
prototipoenstdlib.hcomo:
void*bsearch(constvoid*key,constvoid*base,size_tnmemb,
size_tsize,int(*compar)(constvoid*,constvoid*));

Acontinuacinsemuestraunejemploquehaceusodelafuncinbsearch():
#defineTAM10
#include<stdio.h>
#include<stdlib.h>

typedefstruct{
intllave;
charinformacion[30];
}Registro;
intcompara_registro(voidconst*i,voidconst*j)
{
inta,b;
a=((Registro*)i)>llave;
b=((Registro*)j)>llave;
returnab;
}
main()
{
Registrollave;
Registro*resp;
Registroarreglo[TAM];
intlong_arreglo=TAM;
arreglo[0].llave=43;arreglo[1].llave=9;arreglo[2].llave=0;
arreglo[3].llave=3;arreglo[4].llave=4;arreglo[5].llave=9;
arreglo[6].llave=10;arreglo[7].llave=12;arreglo[8].llave=30;
arreglo[9].llave=203;
printf("Introduceelvalordelallavequesebuscaraenelarreglo:");
scanf("%d",&llave.llave);/*valordelindicequeserabuscado*/
resp=(Registro*)bsearch(&llave,arreglo,long_arreglo,
sizeof(Registro),
compara_registro);
if(resp!=NULL)
printf("Selocalizolallave%d\n",resp>llave);
else
printf("Noselocalizoningunelementoconlallave%d\n",
llave.llave);
}

Lafuncinbsearch()regresaunapuntadoralregistroquecoincideconlallavedada,obien,el
valorNULLsinoencuentraelregistro.
Observarqueeltipodelargumentodelallavedebeserdelmismotipoqueladelarreglodelos
elementos(ennuestrocasoRegistro).

14.5Ejercicios
1. Escribirunprogramaquesimuleellanzamientodeundado.
2. Escribirunprogramaquesimuleelmelate,endondeseseleccionan6nmerosenterosenun
rangode1al44
3. Escribirunprogramaqueleaunnmerodelalneadeentradaygenereunnmeroflotante
aleatorioenelrangode0aelnmerodeentrada.

Subsecciones

15.1Funcionesmatemticas

15.2Constantesmatemticas

15.Biblioteca<math.h>
Labibliotecadematemticasesrelativamentefcildeusar,aligualquelasvistaspreviamente.Se
debeincluirladirectivadepreprocesamiento#include<math.h>,ademsderecordardeligar
labibliotecadematemticasalcompilar:
gccprogmat.coprogmatlm

Unerrorcomneselolvidarincluirelarchivo<math.h>.

15.1Funcionesmatemticas
Semuestraacontinuacinunalistadefuncionesmatemticas.Sonfcilesdeusaryalgunasdeellas
hansidoyausadaspreviamente.Noseproporcionaejemplodelasmismas.

doubleacos(doublex)Calculaelarcocosenodex.
doubleasin(doublex)Calculaelarcosenodex.
doubleatan(doublex)Devuelveelarcotangenteenradianes.
doubleatan2(doubley,doublex)Calculaelarcotangentedelasdosvariables
xey.Essimilaracalcularelarcotangentedey/x,exceptoenquelossignosdeambos
argumentossonusadosparadeterminarelcuadrantedelresultado.
doubleceil(doublex)Redondeaxhaciaarribaalenteromscercano.
doublecos(doublex)devuelveelcosenodex,dondexestdadoenradianes.
doublecosh(doublex)Devuelveelcosenohiperblicodex.
doubleexp(doublex)Devuelveelvalordee(labasedeloslogaritmosnaturales)
elevadoalapotenciax.
doublefabs(doublex)Devuelveelvalorabsolutodelnmeroenpuntoflotantex.
doublefloor(doublex)Redondeaxhaciaabajoalenteromscercano.
doublefmod(doublex,doubley)Calculaelrestodeladivisindexentrey.El
valordevueltoesxn*y,dondeneselcocientedex/y.
doublefrexp(doublex,int*exp)Seempleaparadividirelnmeroxenuna
fraccinnormalizadayunexponentequeseguardaenexp
.
longintlabs(longintj)Calculaelvalorabsolutodeunenterolargo.
doubleldexp(doublex,intexp)Devuelveelresultadodemultiplicarel
nmeroxpor2elevadoaexp(inversadefrexp).
doublelog(doublex);Devuelveellogaritmoneperianodex.
doublelog10(doublex)Devuelveellogaritmodecimaldex.

doublemodf(doublex,double*iptr)Divideelargumentoxenunaparte
enterayunapartefraccional.Laparteenteraseguardaeniptr.
doublepow(doublex,doubley)Devuelveelvalordexelevadoay.
doublesin(doublex)Devuelveelsenodex.
doublesinh(doublex)Regresaelsenohiperblicodex.
doublesqrt(doublex)Devuelvelarazcuadradanonegativadex.
doubletan(doublex)Devuelvelatangentedex.
doubletanh(doublex)Devuelvelatangentehiperblicadex.

15.2Constantesmatemticas
Labibliotecadematemticasdefinevariasconstantes(porlogeneraldesechadas).Siemprees
aconsejableusarestasdefiniciones.

M_ELabasedeloslogaritmosnaturalese.
M_LOG2EEllogaritmodeedebase2.
M_LOG10EEllogaritmodeedebase10.
M_LN2Ellogartimonaturalde2.
M_LN10Ellogaritmonaturalde10.
M_PI
M_PI_2

M_PI_4

M_1_PI

M_2_PI

M_2_SQRTPI

M_SQRT2Larazcuadradapositivade2
M_SQRT1_2Larazcuadradapositivade1/2

Subsecciones

16.1Reportandoerrores
16.1.1

perror()

16.1.2

errno

16.1.3

exit

16.2Flujos
16.2.1Flujospredefinidos

16.2.1.1Redireccionamiento

16.3E/SBasica

16.4E/Sformateada

16.4.1

printf

16.4.2

scanf

16.5Archivos
16.5.1Lecturayescrituradearchivos

sprintf
16.6

y
sscanf

16.6.1Peticindelestadodelflujo

16.7E/Sdebajonivelosinalmacenamientointermedio

16.8Ejercicios

16.Entradaysalida(E/S)stdio.h
Enestecaptulosevernvariasformasdeentradaysalida(E/S).Sehanmencionadobrevemente
algunasformasyahoraserevisarnconunpocomsdedetalle.
LosprogramasquehaganusodelasfuncionesdelabibliotecadeE/Sdebenincluirlacabecera,
estoes:
#include<stdio.h>

16.1Reportandoerrores
EnmuchasocasionesestilreportarloserroresenunprogramadeC.Lafuncindelabiblioteca
estndarperroreslaindicadaparahacerlo.Esusadaconjuntamenteconlavariableerrnoy
frecuentementecuandoseencuentraunerrorsedeseaterminarelprogramaantes.Ademsserevisa
lafuncinexit()yerrno,queenunsentidoestrictonosonpartedelabibliotecastdio.h,para
vercomotrabajanconperror.

16.1.1perror()
Elprototipodelafuncionperrores:
voidperror(constchar*s);

Lafuncinperror()produceunmensajequevaalasalidaestndardeerrores,describiendoel
ltimoerrorencontradoduranteunallamadaalsistemaoaciertasfuncionesdebiblioteca.La
cadenadecaracteressquesepasacomoargumento,semuestraprimero,luegounsignodedos
puntosyunespacioenblanco;porltimo,elmensajeyunsaltodelnea.Paraserdemsutilidad,
lacadenadecaracterespasadacomoargumentodeberaincluirelnombredelafuncinqueincurri
enelerror.Elcdigodelerrorsetomadelavariableexternaerrno,quetomaunvalorcuando
ocurreunerror,peronoespuestaaceroenunallamadanoerrnea.

16.1.2errno
Alavariableespecialdelsistemaerrnoalgunasllamadasalsistema(yalgunasfuncionesde
biblioteca)ledanunvalorentero,paraindicarquehahabidounerror.Estavariableestadefinidaen
lacabecera#include<errno.h>yparaserusadadentrodeunprogramadebeserdeclarada
delasiguienteforma:
externinterrno;

Elvalorsloessignificativocuandolallamadadevolviunerror(usualmente1),algunasveces
unafuncintambinpuededevolver1comovalorvlido,porloquesedebeponererrnoacero
antesdelallamada,parapoderdetectarposibleserrores.

16.1.3exit
Lafuncinexittieneelsiguienteprototipodeacuerdoalacabecera#include<stdlib.h>:
voidexit(intstatus);

Lafuncinproducelaterminacnnormaldelprogramayladevolucindestatusalprocesopadreo
alsistemaoperativo.Elvalordestatusesusadoparaindicarcomohaterminadoelprograma:
o
o

saleconunvalorEXIT_SUCCESSenunaterminacin
saleconunvalorEXIT_FAILUREenunaterminacin

Porlotantocuandoseencuentreunerrorsellamaralafuncincomoexit(EXIT_FAILURE)
paraterminarunprogramaconerrores.

16.2Flujos
Losflujossonunaformaflexibleyeficienteparaleeryescribirdatos.
ExisteunaestructurainternadeC,FILE,lacualrepresentaatodaslosflujosyestadefinidaen
stdio.h.Porlotantosimplementesenecesitareferirsealaestructurapararealizarentraday
salidadedatos.
Parausarlosflujosentoncessedebedeclararunavariableoapuntadordeestetipoenelprograma.
Noserequiereconocermsdetallesacercadeladefinicin.Sedebeabrirunflujoantesderealizar
cualquierE/S,despussepuedeaccesaryentoncessecierra.
ElflujodeE/SusaunBUFFER,esdecir,unpedazofijodereatemporaldelamemoria(elbuffer)
esledooescritoaunarchivo.Losiguientesemuestraenlafigura17.1.Observarqueelapuntador
delarchivoactualmenteapuntaastebuffer.

Figura16.1:Modelodeentradasalidausandounbuffer.
EstoconduceaunusoeficientedeE/Sperosedebetenercuidado:losdatosescritosaunbufferno
aparecenenunarchivo(odispositivo)hastaqueelbufferesescrito(con\nsepuedehacer).
Cualquiersalidaanormaldelcdigopuedecausarproblemas.

16.2.1Flujospredefinidos
EnUNIXsetienenpredefinidos3flujos(enstdio.h):stdin,stdoutystderr.
TodasellasusantextocomomtododeE/S.
Losflujosstdinystdoutpuedenserusadasconarchivos,programas,dispositivosdeE/Scomoel
teclado,laconsola,etc.Elflujostderrsiemprevaalaconsolaolapantalla.
Laconsolaeseldispositivopredefinidoparastdoutystderr.Eltecladoloesparastdin.

Losflujospredefinidossonautomticamenteabiertas.

16.2.1.1Redireccionamiento
LosiguientenoespartedeC,perodependedelsistemaoperativo.Sehaceredireccionamiento
desdelalneadecomandoscon:
>queredireccionastdoutaunarchivo.
Porlotanto,sisetieneunprogramallamadosalida,queusualmentemuestraenpantallaalgo,
entonces:
salida>archivo_sal
mandarlasalidaalarchivoarchivo_sal
<redireccionastdindesdeunarchivoaunprograma.
Porlotanto,siseesperaentradadesdeeltecladoparaunprogramallamadoentrada,sepuedeleer
enformasimilarlaentradadesdeunarchivo.
entrada<archivo_ent
Con|entubamientoopipesecolocastdoutdeunprogramaenstdindeotro,
prog1|prog2
Porejemplo,mandarlasalida(usualmenteaconsola)deunprogramadirectamentealaimpresora
out|lpr

16.3E/SBasica
HayunpardefuncionesquedanlasfacilidadesbsicasdeE/S.Quizslasmscomunesson:
getchar()yputchar().Estndefinidasysonusadascomosigue:

intgetchar(void)leeuncaracterdestdin
intputchar(charch)escribeuncaracterastdoutyregresaelcaracterescrito.

main(){
intch;
ch=getchar();
(void)putchar((char)ch);}

Otrasfuncionesrelacionadasson:
intgetc(FILE*flujo);
intputc(charch,FILE*flujo);

16.4E/Sformateada
SehanvistoyaalgunosejemplosdecomoCusalaE/Sformateada.Enestaseccinserevisarncon
msdetalle.

16.4.1printf
Elprototipodelafuncinestadefinidocomo:
intprintf(constchar*formato,listaarg...);

quemuestraenstdoutlalistadeargumentosdeacuerdoalformatoespecificado.Lafuncin
devuelveelnmerodecaracteresimpresos.
Lacadenadeformateotienedostiposdeobjetos:

caracteresordinariosestossoncopiadosalasalida.
especificadoresdeconversinprecedidospor%ylistadosenlatabla16.1.

Tabla16.1:Caracteresdeformatprintf/scanf
Especificador(%)

Tipo

Resultado

char

unslocaracter

i,d

int

nmerobasediez

int

nmerobaseocho

x,X

int

nmerobasedieciseis

notacinmins/mays

int

char*

impresindecadena

terminadapornulo

enterosinsigno

double/float formatom.ddd...

e,E

"

NotacinCientfica

1.23e002

g,G

"

eflaquesea

mscompacta

caracter%

Entreel%yelcaracterdeformatosepuedeponer:

signomenosparajustificaralaizquierda.
nmeroenteroparaelanchodelcampo.
m.dendondemeselanchodelcampo,ydeslaprecisindedgitosdespusdelpunto
decimaloelnmerodecaracteresdeunacadena.

Porlotanto:
printf("%2.3f\n",17.23478);

lasalidaenpantallaser:
17.235

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

generalasiguientesalida:
VAT=17.5%

16.4.2scanf
Lafuncinestadefinidacomosigue:
intscanf(constchar*formato,listaarg...);

Leedelaentradaestndar(stdin)ycolocalaentradaenladireccindelasvariablesindicadasen
listaargs.Regresaelnmerodecaracteresledos.
Lacadenadecontroldeformateoessimilaraladeprintf.
Importante:serequiereladireccindelavariableounapuntadorconscanf.
Porejemplo:
scanf("%d",&i);

Paraelcasodeunarregloocadenasloserequiereelnombredelmismoparapoderusarscanfya
quecorrespondealiniciodeladireccindelacadena.
charcadena[80];
scanf("%s",cadena);

16.5Archivos
Losarchivossonlaformamscomndelosflujos.

Loprimeroquesedebehaceresabrirelarchivo.Lafuncinfopen()hacelosiguiente:
FILE*fopen(constchar*nomb,constchar*modo);

fopenregresaunapuntadoraunFILE.Enlacadenanombseponeelnombreylatrayectoriadel
archivoquesedeseaaccesar.Lacadenamodocontrolaeltipodeacceso.Siunarchivonopuedeser
accesadoporalgunaraznunapuntadorNULLesdevuelto.
Losmodosson:

``r''lectura;
``w''escritura;y
``a''

Paraabrirunarchivosedebetenerunflujo(apuntadortipoarchivo)queapuntealaestructura
FILE.
Porlotanto,paraabrirunarchivodenominadomiarch.datparalecturaharemosalgocomolo
siguiente;
FILE*flujo;/*Sedeclaraunflujo*/
flujo=fopen("miarch.dat","r");

esunabuenaprcticarevisarsiunarchivosepudoabrircorrectamente
if((flujo=fopen("miarch.dat","r"))==NULL)
{
printf("Nosepudoabrir%s\n","miarch.dat");
exit(1);
}
.....

16.5.1Lecturayescrituradearchivos
Lasfuncionesfprintfyfscanfsoncomnmenteempleadasparaaccesararchivos.
intfprintf(FILE*flujo,constchar*formato,args...);
intfscanf(FILE*flujo,constchar*formato,args...);

Lasfuncionessonsimilaresaprintfyscanfexceptoquelosdatossonledosdesdeelflujo,el
cualdeberserabiertoconfopen().
Elapuntadoralflujoesautomticamenteincrementadocontodaslasfuncionesdelecturay
escritura.Porlotanto,nosedebepreocuparenhacerloanterior.
char*cadena[80];
FILE*flujo;
if((flujo=fopen(...))!=NULL)
fscanf(flujo,"%s",cadena);

Otrasfuncionesparaarchivosson:

intgetc(FILE*flujo)intfgetc(FILE*flujo)
intputc(charch,FILE*s)intfputc(charch,FILE*s)

Estassonparecidasagetcharyputchar.
getcestadefinidacomounamacrodelpreprocesadorenstdio.h.fgetcesunafuncindela
bibliotecadeC.Conambasseconsigueelmismoresultado.
Paraelvolcadodelosdatosdelosflujosadisco,obien,paradisasociarunflujoaunarchivo,
haciendopreviamenteunvolcado,usar:
intfflush(FILE*flujo);
intfclose(FILE*flujo);

Tambinsepuedeteneraccesoalosflujospredeterminadosconfprintf,etc.Porejemplo:
fprintf(stderr,"Nosepuedecalcular!!\n");
fscanf(stdin,"%s",string);

16.6sprintfysscanf
Sonparecidasafprintfyfscanfexceptoqueescriben/leenunacadena.
intsprintf(char*cadena,char*formato,args...)
intsscanf(char*cadena,cahr*formato,args...)

Porejemplo:
floattanque_lleno=47.0;/*litros*/
floatkilometros=400;
charkm_por_litro[80];
sprintf(km_por_litro,"Kilometrosporlitro=%2.3f",kilometros/tanque_lleno);

16.6.1Peticindelestadodelflujo
Existenunascuantasfuncionestilesparaconocerelestadodealgnflujoyquetienenlos
prototipossiguientes:
intfeof(FILE*flujo);
intferror(FILE*flujo);
voidclearerr(FILE*flujo);
intfileno(FILE*flujo);

feof()devuelveverdaderosielflujoindicadoestaenelfindelarchivo.Porlotantoparaleer
unflujo,fp,lneaalneasepodrahaceralgocomo:
while(!feof(fp))
fscanf(fp,"%s",linea);

ferror()inspeccionaelindicadordeerrorparaelflujoindicado,regresandoverdaderosiun

errorhaocurrido.
clearerr()limpialosindicadoresdefindeficheroyerrorparaelflujoindicado.
fileno()examinaelargumentoflujoydevuelvesudescriptordefichero,comounentero.

16.7E/Sdebajonivelosinalmacenamiento
intermedio
EstaformadeE/Sessinbuffercadarequerimientodelectura/escriturageneraunaccesoaldisco(o
dispositivo)directamenteparatraer/ponerundeterminadonmerodebytes.
Nohayfacilidadesdeformateoyaqueseestnmanipulandobytesdeinformacin.
Loanteriorsignificaqueseestanusandoarchivosbinarios(ynodetexto).
Envezdemanejarapuntadoresdearchivos,seempleaunmanejadordearchivodebajonivelo
descriptordearchivo,elcualdaunenteronicoparaidentificarcadaarchivo.
Paraabrirunarchivousar:
intopen(char*nomb,intflag);

queregresaundescriptordearchivo1sifalla.
flagcontrolaelaccesoalarchivoytienelossiguientesmacrosdefinidasenfcntl.h:

O_APPENDelarchivoseabrirenmododesloaadir
O_CREATsielarchivonoexiste,sercreado.
O_EXCLabrirenformaexclusiva.
O_RDONLYslolectura
O_RDWRlecturayescritura
O_WRONLYsloescritura

paraverotrasopcionesusarman.
Lafuncin:
intcreat(char*nomb,intperms);

puedetambinserusadaparacrearunarchivo.
Otrasfuncionesson:
intclose(intfd);
intread(intfd,char*buffer,unsignedlongitud);
intwrite(intfd,char*buffer,unsignedlongitud);

quepuedenserusadasparacerrarunarchivoyleer/escribirundeterminadonmerodebytesdela
memoria/haciaunarchivoenlalocalidaddememoriaindicadaporbuffer.

Lafuncinsizeof()escomnmenteusadaparaindicarlalongitud.
Lasfuncionesreadywriteregresanelnmerodebytesledos/escritoso1sifallan.
Setieneacontinuacindosaplicacionesqueusanalgunasdelasfuncionesindicadas:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
main(intargc,char**argv)
{
floatbuffer[]={23.34,2.34,1112.33};
intdf;
intbytes_esc;
intnum_flot;
/*Primeramentesecreaelarchivo*/
if((df=open(argv[1],O_CREAT,S_IRUSR|S_IWUSR))==1)
{/*Error,archivonoabierto*/
perror("Archivodatos,apertura");
exit(1);
}
else
printf("Descriptordearchivo%d\n",df);
/*Despuesseabreparasolamenteescribir*/
if((df=open(argv[1],O_WRONLY))==1)
{/*Error,archivonoabierto*/
perror("Archivodatos,apertura");
exit(1);
}
else
printf("Descriptordearchivo%d\n",df);
/*Enprimerlugarseescribeelnumerodeflotantesqueseranescritos
*/
num_flot=3;
if((bytes_esc=write(df,&num_flot,sizeof(int)))==1)
{/*Errorenlaescritura*/
perror("Archivodatos,escritura");
exit(1);
}
else
printf("Escritos%dbytes\n",bytes_esc);

/*Seescribeelarreglodeflotantes*/
if((bytes_esc=write(df,buffer,num_flot*sizeof(float)))==1)
{/*Errorenlaescritura*/
perror("Archivodatos,escritura");
exit(1);
}
else
printf("Escritos%dbytes\n",bytes_esc);
close(df);
}

Ejemplodelecturadelejemploanterior:

/*Esteprogramaleeunalistadeflotantesdeunarchivobinario.*/
/*Elprimerbytedelarchivoesunenteroindicandocuantos*/
/*flotanteshayenelarchivo.Losflotantesestandespuesdel*/
/*entero,elnombredelarchivosedaenlalineadecomandos.*/
#include<stdio.h>
#include<fcntl.h>
main(intargc,char**argv)
{
floatbuffer[1000];
intfd;
intbytes_leidos;
intnum_flot;
if((fd=open(argv[1],O_RDONLY))==1)
{/*Error,archivonoabierto*/
perror("Archivodatos");
exit(1);
}
if((bytes_leidos=read(fd,&num_flot,sizeof(int)))==1)
{/*Errorenlalectura*/
exit(1);
}

if(num_flot>999){/*archmuygrande*/exit(1);}
if((bytes_leidos=read(fd,buffer,num_flot*sizeof(float)))==1)
{/*Errorenlalectura*/
exit(1);
}
}

16.8Ejercicios
1. Escribirunprogramaparacopiarunarchivoenotro.Los2nombresdelosarchivosson
dadoscomolosprimerosargumentosdelprograma.
Copiarbloquesde512bytescadavez.
Revisarqueelprograma:
tengadosargumentosomostrar"Elprogramarequieredos
argumentos";
elprimernombredearchivoseadelecturaomostrar"Nose
puedeabrirarchivo...paralectura";
queelsegundonombredelarchivoseadeescrituraomostrar"No
sepuedeabrirarchivo...paraescritura".

2. Escribirunprograma"ultimas"quemuestrelasltimasnlneasdeunarchivodetexto.ny
elnombredelarchivodebernespecificarsedesdelalneadecomandos.Pordefecton
deberser5.Elprogramadeberhacerelmejorusodelespaciodealmacenamiento.
3. Escribirunprogramaquecomparedosarchivosymuestrelaslneasquedifieran.Tip:
buscarrutinasapropiadasparamanejodecadenasymanejodearchivos.Elprogramano
debersermuygrande.

Subsecciones

17.1Funcionesbsicasparaelmanejodecadenas
17.1.1Bsquedaencadenas

17.2Pruebayconversindecaracteres<ctype.h>

17.3Operacionesconlamemoria
<memory.h>

17.4Ejercicios

17.Manejodecadenas<string.h>
Recordandolapresentacindearregloshecha(captulo5)endondelascadenasestndefinidas
comounarreglodecaracteresounapuntadoraunaporcindememoriaconteniendocaracteres
ASCII.UnacadenaenCesunasecuenciadeceroomscaracteresseguidasporuncaracterNULLo
\0:

Figura17.1:Representacindeunarreglo.
EsimportantepreservarelcaracterdeterminacinNULL,yaqueconsteescomoCdefiney
manejalaslongitudesdelascadenas.TodaslasfuncionesdelabibliotecaestndardeClorequieren
paraunaoperacinsatisfactoria.
Engeneral,apartedealgunasfuncionesrestringidasenlongitud(strncat(),strncmp()y
strncpy()),almenosquesecreencadenasamano,nosedebernencontrarproblemas.Se
debernusarlasfuncionesparamanejodecadenasynotratardemanipularlascadenasenforma
manualdesmantelandoyensamblandocadenas.

17.1Funcionesbsicasparaelmanejode
cadenas
Todaslasfuncionesparamanejodecadenastienensuprototipoen:
#include<string.h>

Lasfuncionesmscomunessondescritasacontinuacin:

char*strcpy(constchar*dest,constchar*orig)Copialacadenadecaracteresapuntada
pororig(incluyendoelcarcterterminador'\0')alvectorapuntadopordest.Las

cadenasnodebensolaparse,yladedestino,debesersuficientementegrandecomopara
alojarlacopia.
intstrcmp(constchar*s1,constchar*s2)Comparalasdoscadenasdecaracteress1y
s2.Devuelveunenteromenor,igualomayorquecerosiseencuentraques1es,
respectivamente,menorque,iguala,omayorques2.
char*strerror(interrnum)Devuelveunmensajedeerrorquecorrespondeaunnmerode
error.
intstrlen(constchar*s)Calculalalongituddelacadenadecaracteres.
char*strncat(char*s1,constchar*s2,size_tn)Agregancaracteresdes2as1.
intstrncmp(constchar*s1,char*s2,size_tn)Comparalosprimerosncaracteresdedos
cadenas.
char*strncpy(constchar*s1,constchar*s2,size_tn)Copialosprimerosncaracteresde
s2as1.
strcasecmp(constchar*s1,constchar*s2)versinqueignorasisonmaysculaso
minsculasdestrcmp().
strncasecmp(constchar*s1,constchar*s2,size_tn)versininsensibleamaysculaso
minsculasdestrncmp()quecomparalosprimerosncaracteresdes1.

Elusodemuchasfuncionesesdirecto,porejemplo:
char*s1="Hola";
char*s2;
intlongitud;
longitud=strlen("Hola");/*long=4*/
(void)strcpy(s2,s1);

Observarquetantostrcat()ystrcopy()regresanunacopiadesuprimerargumento,elcual
eselarreglodestino.Observartambinqueordendelosargumentosesarreglodestinoseguidopor
arreglofuentelocualavecesesunasituacinparahacerloincorrectamente.
Lafuncinstrcmp()comparalexicogrficamentelasdoscadenasyregresa:

Menorquecerosis1eslxicamentemenorques2;
Cerosis1ys2sonlxicamenteiguales;
Mayorquecerosis1eslxicamentemayorques2;

Lasfuncionesdecopiadostrncat(),strncmp()ystrncpy()sonversionesms
restringidasquesuscontrapartesmsgenerales.Realizanunatareasimilar,perosolamenteparalos
primerosncaracteres.ObservarqueelcaracterdeterminacinNULLpodraservioladocuandose
usaestasfunciones,porejemplo:
char*s1="Hola";
char*s2=2;
intlongitud=2;
(void)strncpy(s2,s1,longitud);/*s2="Ho"*/

dondes2notieneelterminadorNULL.

17.1.1Bsquedaencadenas
Labibliotecatambinproporcionavariasfuncionesdebsquedaencadenas.

char*strchr(constchar*s,intc)Devuelveunpunteroalaprimeraocurrenciadelcarcter
cenlacadenadecaracteress.
char*strrchr(constchar*s,intc)Encuentralaltimaocurrenciadelcaractercenla
cadena.
char*strstr(constchar*s1,constchar*s2)Localizalaprimeraocurrenciadelacadenas2
enlacadenas1.
char*strpbrk(constchar*s1,constchar*s2)Regresaunapuntadoralaprimera
ocurrenciaenlacadenas1decualquiercarcterdelacadenas2,ounapuntadornulosino
hayuncaracterdes2queexistaens1.
size_tstrspn(constchar*s1,constchar*s2)Calculalalongituddelsegmentoinicialdes1
queconstanicamentedecaracteresens2.
size_tstrcspn(constchar*s1,constchar*s2)Regresaelnmerodecaracteresalprincipio
des1quenocoincidencons2.
char*strtok(char*s1,constchar*s2)Dividelacadenaapuntadaas1enunasecuenciade
``tokens'',cadaunodeellosestadelimitadoporunoomscaracteresdelacadenaapuntada
pors2.

Lasfuncionesstrchr()ystrrchr()sonlasmssimplesdeusar,porejemplo:
char*s1="Hola";
char*resp;
resp=strchr(s1,'l');

Despusdelaejecucin,respapuntaalalocalidads1+2.
Lafuncinstrpbrk()esunafuncinmsgeneralquebuscalaprimeraocurrenciadecualquier
grupodecaracteres,porejemplo:
char*s1="Hola";
char*resp;
res=strpbrk(s1,"aeiou");

Enestecaso,respapuntaalalocalidads1+1,lalocalidaddelaprimerao.
Lafuncinstrstr()regresaunapuntadoralacadenadebsquedaespecificadaounapuntador
nulosilacadenanoesencontrada.Sis2apuntaaunacadenadelongitudcero(estoes,lacadena
""),lafuncinregress1.Porejemplo:
char*s1="Hola";
char*resp;
resp=strstr(s1,"la");

lacualtendrresp=s1+2.
Lafuncinstrtok()esunpocomscomplicadaencuantoaoperacin.Sielprimerargumento

noesNULLentonceslafuncinencuentralaposicindecualquieradeloscaracteresdelsegundo
argumento.Sinembargo,laposicinesrecordadaycualquirllamadasubsecuenteastrtok()
iniciarensaposicinsienestassubsecuentesllamadaselprimerargumentonoesNULL.Por
ejemplo,sideseamosdividirlacadenas1usandocadaespacioeimprimircada``token''enuna
nuevalneaharamoslosiguiente:
chars1[]="Holamuchachogrande";
char*t1;
for(t1=strtok(s1,"");
t1!=NULL;
t1=strtok(NULL,""))
printf("%s\n",t1);

Seempleauncicloforenunaformanoregulardeconteo:

Enlainicializacinsellamaalafuncinstrtok()conlacadenas1.
Seterminacuandot1esNULL.
Seestaasignandotokensdes1at1hastalaterminacinllamandoastrtok()conel
primerargumentoNULL.

17.2Pruebayconversindecaracteres
<ctype.h>
Unabibliotecarelacionada#include<ctype.h>lacualcontienemuchasfuncionestilespara
convertiryprobarcaracteresindividuales.
Lasfuncionesmscomunespararevisarcaracterestienenlossiguientesprototipos:

intisalnum(intc)Verdadsicesalfanumrico.
intisalpha(intc)Verdadsicesunaletra.
intisascii(intc)VerdadsicesASCII.
intiscntrl(intc)Verdadsicesuncaracterdecontrol.
intisdigit(intc)Verdadsicesundgitodecimal.
intisgraph(intc)Verdadsicesuncaracterimprimible,exceptuandoelespacioenblanco.
intislower(intc)Verdadsicesunaletraminscula.
intisprint(intc)Verdadsicesuncaracterimprimible,incluyendoelespacioenblanco.
intispunct(intc)Verdadsicesunsignodepuntuacin.
intisspace(intc)Verdadsicesunespacio
intisupper(intc)Verdadsicesunaletramayscula.
intisxdigit(intc)Verdadsicesundgitohexadecimal.

Lasfuncionesparaconversindecaracteresson:

inttoascii(intc)ConviertecaASCIIoununsignedcharde7bits,borrandolosbits
altos.
inttolower(intc)Conviertelaletracaminsculas,siesposible.
inttoupper(intc)Conviertelaletracamaysculas,siesposible.

Elusodeestasfuncionesesdirectoyporlotanto,nosedanejemplos.

17.3Operacionesconlamemoria
<memory.h>
Finalmenteseverunresumendealgunasfuncionesbsicasdememoria.Sinembargo,noson
funcionesestrictamentedecadenas,perotienensuprototipoen#include<string.h>:

void*memchr(void*s,intc,size_tn)Buscauncaracterenunbuffer.
intmemcmp(void*s1,void*s2,size_tn)Comparadosbuffers.
void*memcpy(void*dest,void*fuente,size_tn)Copiaunbufferdentrodeotro.
void*memmove(void*dest,void*fuente,size_tn)Mueveunnmerodebytesdeunbuffer
aotro.
void*memset(void*s,intc,size_tn)Ponetodoslosbytesdeunbufferauncaracterdado.

Elusodeestasfuncionesesdirectoyparecidoalasoperacionesdecomparacindecaracteres
(exceptoquelalongitudexacta(n)detodaslasoperacionesdeberserindicadayaquenohayuna
formapropiadeterminacin).
Observarqueentodosloscasosbytesdememoriasoncopiados,porloquelafuncinsizeof()
ayudaenestoscasos,porejemplo:
charfuente[TAM],dest[TAM];
intifuente[TAM],idest[TAM];
memcpy(dest,fuente,TAM);/*Copiachars(bytes)OK*/
memcpy(idest,ifuente,TAM*sizeof(int));/*Copiaarreglodeenteros*/

Lafuncinmemmove()secomportadelamismaformaquememcpy()exceptoquelas
localidadesdelafuenteyeldestinopodrantraslaparse.
Lafuncinmemcmp()essimilarastrcmp()exceptoqueunsignedbytessoncomparadosyse
devuelvecerosis1esmenorques2,etc.

17.4Ejercicios
1. Escribirunafuncinsimilarastrlenquepuedamanejarcadenassinterminador.Tip:se
necesitarconocerypasarlalongituddelacadena.
2. Escribirunafuncinqueregreseverdad,siunacadenadeentradaesunpalndromo.Un
palndromoesunapalabraqueseleeigualdeizquierdaaderecha,odederechaaizquierda.
Porejemplo,ANA.
3. Sugerirunaposibleimplementacindelafuncinstrtok():
1. usandootrasfuncionesdemanejodecadenas.
2. desdelosprincipiosdeapuntadores.
Cmoselograelalmacenamientodeunacadenaseparada?
4. Escribirunafuncinqueconviertatodosloscaracteresdeunacadenaamaysculas.

5. Escribirunprogramaqueinviertaelcontenidodelamemoriaenbytes.Esdecir,sisetienen
nbytes,elbytedememorianseinvierteconelbyte0,elbyten1seintercambiaconelbyte
1,etc.

Subsecciones

18.1Funcionesparaelmanejodedirectorios<unistd.h>

18.1.1Busquedayordenamientodedirectorios:

sys/types.h

,sys/dir.h

18.2Rutinasdemanipulacindearchivos:unistd.h,sys/types.h,sys/stat.h
18.2.1Permisosdeaccesosaarchivos

18.2.1.1errno

18.2.2Estadodeunarchivo

18.2.3Manipulacindearchivos:stdio.h,unistd.h

18.2.4Creacindearchivostemporales:

<stdio.h>

18.3Ejercicios

18.AccesodeArchivosyllamadasalsistema
dedirectorios
Existenmuchasutilerasquepermitenmanipulardirectoriosyarchivos.Loscomandoscd,ls,rm,
cp,mkdir,etc.sonejemplosquehansidorevisadosyaenelsistemaoperativo.
SerevisarenestecaptulocomohacerlasmismastareasdentrodeunprogramaenC.

18.1Funcionesparaelmanejodedirectorios
<unistd.h>
Pararealizarloserequierellamarlasfuncionesapropiadaspararecorrerlajerarquadedirectorioso
preguntarsobreloscontenidosdelosdirectorios.

intchdir(char*path)cambiaaldirectorioindicadoenlacadenapath.

char*getcwd(char*path,size_ttam)Obtienelatrayectoriacompleta,esdecir,desdela
razdeldirectorioactual.pathesunapuntadoraunacadenadondelatrayectoriaser
regresada.LafuncindevuelveunapuntadoralacadenaoNULLsiunerrorocurre.

SetieneacontinuacinlaemulacindelcomandocddeUnixconC:
#include<stdio.h>
#include<unistd.h>
#defineTAM80
main(intargc,char**argv)

{
charcadena[TAM];
if(argc<2)
{
printf("Uso:%s<directorio>\n",argv[0]);
exit(1);
}
if(chdir(argv[1])!=0)
{
printf("Erroren%s.\n",argv[0]);
exit(1);
}
getcwd(cadena,TAM);
printf("Eldirectorioactuales%s\n",cadena);
}

18.1.1Busquedayordenamientodedirectorios:
sys/types.h,sys/dir.h
Dosfuncionestiles(enplataformasBSDyaplicacionesnomultithread)estndisponibles:
intscandir(constchar*dir,structdirent**listanomb,
int(*select)(conststructdirent*),
int(*compar)(conststructdirent**,conststructdirent**)
Estafuncinrastreaeldirectoriodir,llamandoselect()encadaentradadedirectorio.Las
entradasparalasqueselect()devuelveunvalordistintodecerosealmacenanencadenasquese
asignandelamemoriaconmalloc(),ordenadasusandoqsort()conlafuncinde
comparacincompar(),ypuestasenlamatrizlistanomb.SiselectesNULL,se
seleccionantodaslasentradas.
intalphasort(conststructdirent**a,conststructdirent**b);
Puedeserusadacomofuncindecomparacinparaquelafuncinscandir()pongalasentradas
dedirectorioenordenalfabtico.
AcontinuacinsetieneunaversinsimpledelcomandodeUNIXls
#include<dirent.h>
#include<unistd.h>
#include<sys/param.h>
#include<stdio.h>

#defineFALSO0
#defineVERDADERO!FALSO

externintalphasort();

chartrayectoria[MAXPATHLEN];

main()
{
intcontar,i;
structdirent**archivos;
intselecc_arch();

if(getwd(trayectoria)==NULL)
{
printf("Errorobteniendolatrayectoriaactual\n");
exit(0);
}
printf("Directoriodetrabajoactual:%s\n",trayectoria);
contar=scandir(trayectoria,&archivos,selecc_arch,alphasort);

/*Sinoseencontraronarchivos*/
if(contar<=0)
{
printf("Nohayarchivosenestedirentorio\n");
exit(0);
}
printf("Hay%darchivos.\n",contar);
for(i=0;i<contar;++i)
printf("%s",archivos[i]>d_name);
printf("\n");/*flushbuffer*/
}
intselecc_arch(structdirent*entry)
{
if((strcmp(entry>d_name,".")==0)||
(strcmp(entry>d_name,"..")==0))
return(FALSO);
else
return(VERDADERO);
}

scandirregresalospseudodirectorios(.),(..)ytambintodoslosarchivos.Enesteejemplose
filtranlospseudodirectoriosparaquenosemuestrenhaciendoquelafuncinregreseFALSO.
Losprototiposdelasfuncionesscandiryalphasorttienendefinicionesenlacabecera
dirent.h
MAXPATHLENestadefinidaensys/param.hylafuncingetwd()enunistd.h.
Sepuedeirmslejosqueloanteriorybuscarporarchivosparticulares.
Reescribiendolafuncinselecc_archparaqueslomuestrelosarchivosconlossufijos.c,.h
y.o.
intselecc_arch(structdirent*entry)
{
char*ptr;

if((strcmp(entry>d_name,".")==0)||
(strcmp(entry>d_name,"..")==0))
return(FALSO);
/*Revisarlasextensionesdelosarchivos*/
ptr=rindex(entry>d_name,'.');/*Probarquetengaunpunto*/
if((ptr!=NULL)&&
((strcmp(ptr,".c")==0)
||(strcmp(ptr,".h")==0)

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

Lafuncinrindex()esunafuncinparamanejodecadenasqueregresaunapuntadoralaltima
ocurrenciadelcaractercenlacadenas,ounapuntadorNULLsicnoocurreenlacadena.
(index()esunafuncinsimilarperoasignaunapuntadoralaprimeraocurrencia.)

18.2Rutinasdemanipulacindearchivos:
unistd.h,sys/types.h,sys/stat.h
Existenvariasllamadasalsistemaquepuedenseraplicadasdirectamentealosarchivosguardados
enundirectorio.

18.2.1Permisosdeaccesosaarchivos
Lafuncinintaccess(constchar*trayectoria,intmodo);determinalos
permisosdeusuarioparaunfichero,deacueroconmodo,queestadefinidoen#include
<unistd.h>,loscualespuedenser:

R_OKpruebaelpermisodelectura.
W_OKpruebaelpermisodeescritura.
X_OKpruebaelpermisodeejecucinobsqueda.
F_OKpruebasisepermitelacomprobacindelaexistenciadelfichero.

Lafuncinaccess()regresa:0sihahabidoxito,o1encasodefallayaerrnoseleasigna
unvaloradecuado.Verlaspginasdelmanparaverlalistadeerrores.

18.2.1.1errno
Algunasllamadasalsistema(yalgunasfuncionesdebiblioteca)danunvaloralenteroerrnopara
indicarquehahabidounerror.Estaesunavariableespecialdelsistema.
ParausarerrnoenunprogramadeC,debeserdeclaradodelasiguienteforma:
externinterrno;

EstapuedesermanualmentepuestodentrodeunprogramaenC,deotraformasimplementeretiene
elltimovalor.
Lafuncinintchmod(constchar*trayectoria,mode_tmodo);cambiaelmodo
delarchivodadomediantetrayectoriaparaunmododado.

chmod()devuelve0encasodexitoy1encasodeerrorademsseasignaalavariableerrno
unvaloradecuado(revisarlaspginasdemanparaverlostiposdeerrores)

18.2.2Estadodeunarchivo
Setienendosfuncionestilesparaconocerelestadoactualdeunarchivo.Porejemplosepuede
sabequetangrandeesunarchivo(st_size),cuandofuecreado(st_ctime),etc(verladefinicindela
estructuraabajo).Lasdosfuncionestienensusprototiposen<sys/stat.h>

intstat(constchar*nomb_arch,structstat*buf)obtieneinformacinacercadelarchivo
apuntadopornomb_arch.Noserequierenpermisosdelectura,escrituraoejecucin,pero
todoslosdirectorioslistadosennomb_archdebernestardisponibles.

intfstat(intdesarch,structstat*buf)obtienelamismainformacinqueelanterior,pero
sloelarchivoabiertoapuntadopordesarch(talycomolodevuelveopen())es
examinadoenlugardenomb_arch.

Lasfuncionesstat()yfstat()regresan0encasoxito,1sihuboerroryerrnoes
actualizadoapropiadamente.
bufesunapuntadoralaestructurastatenlacuallainformacinescolocada.Laestructura
statestadefinidaeninclude<sys/stat.h>,comosigue:
structstat
{
dev_tst_dev;/*dispositivo*/
ino_tst_ino;/*inodo*/
mode_tst_mode;/*proteccion*/
nlink_tst_nlink;/*numerodeenlacesfisicos*/
uid_tst_uid;/*IDdelusuariopropietario*/
gid_tst_gid;/*IDdelgrupopropietario*/
dev_tst_rdev;/*tipodispositivo(sies
dispositivoinodo)*/
off_tst_size;/*tamaototal,enbytes*/
unsignedlongst_blksize;/*tamaodebloqueparael
sistemadeficherosdeE/S*/
unsignedlongst_blocks;/*numerodebloquesasignados*/
time_tst_atime;/*horaultimoacceso*/
time_tst_mtime;/*horaultimamodificacion*/
time_tst_ctime;/*horaultimocambio*/
};

Semuestraunejemploquehaceusodelafuncinstat:
#include<stdio.h>
#include<sys/stat.h>/*Paralaestructurastat*/
#include<unistd.h>
main(intargc,char**argv)
{
structstatbuf;
printf("%s\n",argv[0]);

if(stat(argv[0],&buf)==1)
{

perror(argv[0]);
exit(1);
}
else
{
printf("Tamaodelarchivo%s%dbytes.\n",argv[0],buf.st_size);
}
}

18.2.3Manipulacindearchivos:stdio.h,unistd.h
Existenalgunasfuncionesparaborraryrenombrararchivos.Quizslaformamscomnesusando
lasfuncionesdestdio.h:
intremove(constchar*pathname);
intrename(constchar*viejo,constchar*nuevo);

Dosllamadasalsistema(definidasenunistd.h)lascualessonactualmenteusadasporlas
funcionesremove()yrename()tambinexisten,perosonprobablementemsdficilesde
recordar,almenosqueseestesuficientementefamiliarizadoconUNIX.

intunlink(constchar*pathname);borraunnombredelsistemadearchivos.Sidicho
nombreeraelltimoenlaceaunarchivo,yningnprocesotieneelarchivoabierto,el
ficheroesborradoyelespacioqueocupabavuelveaestardisponible.Regresa0encasode
xito,1encasodeerroryponeunvalorenerrnoparaindicarlo.

intlink(constchar*oldpath,constchar*newpath);creaunnuevoenlace(tambin
conocidocomoenlacefsicoaunarchivoexistente.

Lasfuncionesstat()yfstat()regresan0encasoxito,1sihuboerroryponelavariable
errnoconalgnvalorindicandoeltipodeerror.

18.2.4Creacindearchivostemporales:<stdio.h>
Losprogramasconfrecuencianecesitancreararchivosslodurantelavidadeunprograma.Existen
dosfuncionesconvenientes(ademsdealgunasvariantes)paralarealizacindelatarea
mencionada.Elmanejo(borradodearchivos,etc.)estomadoconcuidadoporelsistemaoperativo.
LafuncinFILE*tmpfile(void);creaunarchivotemporal(enmododelectura/escritura
binaria)yabreelcorrespondienteflujo.Elarchivoseborrarautomticamentecuandoelprograma
termine.
Lafuncinchar*tmpnam(char*s);creaunnombrenicoparaunarchivotemporalusando
elprefijodetrayectoraP_tmpdirdefinidoen<stdio.h>.

18.3Ejercicios
1. EscribirunprogramaenCparasimularelcomandolsldeUNIXquemuestretodoslos

archivosdeldirectorioactual,suspermisos,tamao,etc.
2. Escribirunprogramaparamostrarlaslneasdeunarchivoquecontengaunapalabradada
comoargumentoalprograma,esdecir,unaversinsencilladelautilidadgrepdeUNIX.
3. Esribirunprogramaparamostrarunalistadearchivosdadoscomoargumentos,parando
cada20lneashastaqueunateclaseapresionada(unaversinsimpledelautileramorede
UNIX).
4. Escribirunprogramaquelistetodoslosarchivosdeldirectorioactualytodoslosarchivosen
lossubsecuentesdirectorios.

Subsecciones

19.1Funcionesbsicasparaeltiempo

19.2Ejemplosdeaplicacionesdefuncionesdeltiempo.

19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralgnclculo.

19.2.2Ejemplo2:Inicializarlasemilladeunnmeroaleatorio.

19.3Ejercicios

19.Funcionesparaeltiempo
EnestecaptuloserevisarcomosepuedeusarelrelojconllamadasalsistemaUNIX.
Existenmuchasfuncionesparaeltiempoquelasquesernconsideradasaquusarlaspginasde
manyloslistadosdelabibliotecaestndardefuncionesparamsdetalles.
Elusomscomndelasfuncionesdetiemposon:

conocereltiempo,
tomareltiempoaprogramasyfuncionesy
ponervaloresasemillas.

19.1Funcionesbsicasparaeltiempo
Algunasprototiposdelasfuncionesbsicasparaeltiemposonlassiguientes:

time_ttime(time_t*t)devuelveeltiempotranscurrido,medidoensegundosdesde``la
poca''0horas,0minutos,0segundos,tiempouniversalcoordinado(GMT)del1^odeenero
de1970.Estamedidasellamael``tiempodecalendario''.Sitnoesnulo,elvalordevuelto
tambinseguardaenlazonadememoriaalaqueapuntat.Encasodeerror,sedevuelve
((time_t)1)yseasignaalavariableerrnounvalorapropiado.

ftime(structtimeb*pt)devuelvelahoraylafechaactualesenpt,queestadeclaradaen
<sys/timeb.h>comosigue:
structtimeb
{
time_ttime;/*Segundosdesdeepoca,igualque
`time'.*/
unsignedshortintmillitm;/*millisegundosadicionales.
*/
shortinttimezone;/*Tiempolocalmedidoenminutos
oestedeGMT.*/
shortintdstflag;/*Nocerosiseusahorariodeverano
*/

};

Encasodexito,sedevuelveeltiempotranscurridoensegundosdesdelapoca.Encasode
error,sedevuelve((time_t)1)yseasignaalavariableerrnounvalorapropiado.

char*ctime(time_t*timep)tomaunargumentodetipotime_t(longinteger)que
representaeltiempodecalendadrioyloconvierteaunacadenade26caracteresdelaforma
producidaporlafuncinasctime().Enprimerlugardescomponelossegundosauna
estructuratmllamandoalocaltime(),yentoncesllamaaasctime()paraconvertir
laestructuratmaunacadena.

char*asctime(conststructtm*timeptr)convierteunvalordetiempocontenidoenuna
estructuratmaunacadenade26caracteresdelaforma:
dddmmmddhh:mm:ssaaaa
Lafuncinasctime()regresaunapuntadoralacadena.

19.2Ejemplosdeaplicacionesdefuncionesdel
tiempo.
Comosemencionopreviamente,bsicamenteexistentresposiblesusosdelasfuncionesdetiempo.

19.2.1Ejemplo1:Tiempo(ensegundos)parahaceralgn
clculo.
Esteesunejemplosencilloqueilustralasllamadasalafuncintiempoendistintosmomentos:
/*timer.c*/
#include<stdio.h>
#include<sys/types.h>
#include<time.h>
main()
{
inti,j;
time_tt1,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++);/*Unpequeoretardo*/
}
(void)time(&t2);
printf("\nTiempoparahacer300cuadradosycubos=%dsegundos\n",
(int)t2t1);
}

19.2.2Ejemplo2:Inicializarlasemilladeunnmero
aleatorio.
Sehavistounejemplosimilarpreviamente,enestaocasinseusalafuncinlrand48()para
generarunasecuenciadenmeros:
/*random.c*/
#include<stdio.h>
#include<sys/types.h>
#include<time.h>
main()
{
inti;
time_tt1;
(void)time(&t1);
srand48((long)t1);
/*usartimeensegundosparaponerlasemilla*/
printf("5numerosaleatorios(semilla=%d):\n",(int)t1);
for(i=0;i<5;++i)
printf("%d",lrand48());
printf("\n\n");
}

Lafuncinlrand48()devuelveenteroslargosnonegativosdistribuidosuniformememnteentre0
y

Unafuncinsimilareslafuncindrand48queregresanmerosdedobleprecisinenelrango
.
srand48()poneelvalordelasemillaparaestosgeneradoresdenmerosaleatorios.Es
importantetenerdiferentessemillascuandosellamealasfuncionesdeotraformaelmismo
conjuntonmerospseudoaleatoriosseragenerados.Lafuncintime()siempredaunasemilla
nica(siempreycuandohayatranscurridoporlomenos1segundo).

19.3Ejercicios
1. EscribirunprogramaenCquemidaeltiempodeunfragmentodecdigoenmilisegundos.
2. EscribirunprogramaenCparaproducirunaseriedenmerosaleatoriosdepuntoflotante
enlosrangosa)0.01.0,b)0.0n,dondenescualquiervalorflotante.Lasemilladeber
estarpuestaparaquesegaranticeunasecuencianica.

Subsecciones

20.1EjecutandocomandosdeUNIXdesdeC

20.2
execl()

20.3
fork()

20.4
wait()

20.5
exit()

20.6Ejercicios

20.Controldeprocesos:<stdlib.h>,
<unistd.h>
Unprocesoesbsicamenteunnicoprogramaejecutndose.Estepodraserunprogramadel
''sistema(porejemplo,login,csh,update,etc).unprogramainiciadoporelusuario(gimpo
algunohechoporelusuario).
CuandoUNIXejecutaunprocesoleasignaacadprocesounnmeronicoprocessIDopid.
ElcomandopsdeUNIXlistatodoslosprocesosqueseestnejecutandoenlamquina,listando
tambinelpid.
LafuncindeCintgetpid()regresarelpiddeunprocesoquellameaestafuncin.
Unprogramausualmenteejecutaunsloproceso.Sinembargodespuessevercomosepuede
hacerqueunprogramacorracomovariosprocesosseparadoscomunicados.

20.1EjecutandocomandosdeUNIXdesdeC
SepuedenejecutarcomandosdesdeunprogramadeCcomosiseestuvieraenlalneadecomandos
deUNIXusandolafuncinsystem().NOTA:sepuedeahorrarbastantetiempoyconfusinen
vezdeejecutarotrosprogramas,scripts,etc.parahacerlastareas.
intsystem(char*mandato)dondemandatopuedeserelnombredeunautilerade
UNIX,unshellejecutableounprogramadelusuario.Lafuncinregresaelstatusdesalidadel
shell.Lafuncintienesuprototipoen<stdlib.h>
Ejemplo:llamadadelcomandolsdesdeunprograma
main()
{
printf("Archivoseneldirectorioson:\n");
system("lsl");
}

Lafuncinsystemesunallamadaqueestaconstruidadeotras3llamadasdelsistema:execl(),
wait()yfork()(lascualestienensuprototipoen<unistd.h>).

20.2execl()
Lafuncinexecltieneotras5funcionesrelacionadasverlaspginasdeman.
Lafuncinexeclrealizalaejecucin(execute)ysale(leave),esdecirqueunprocesoser
ejecutadoyentoncesterminadoporexecl.
Estadefinidacomo:
execl(constchar*camino,constchar*arg0,...,char*argn,0);

Elltimoparmetrodebersersiempre .EsteesunterminadorNulo.Comolalistade
argumentosseavariablesedebeindicardealgunaformaaCcuandoseterminelalista.El
terminadornulohaceloanterior.
Elapuntadorcaminoindicaelnombredeunarchivoquecontieneelcomandoqueserejecutado,
arg0apuntaaunacadenaqueeselmismonombre(oalmenossultimocomponente).
arg1,...,argnsonapuntadoresalosargumentosparaelcomandoyel solamenteindica
elfindelalistadeargumentosvariables.
Porlotantonuestroejemploquedadelasiguienteforma:
#include<unistd.h>
main()
{
printf("Losarchivoseneldirectorioson:\n");
execl("/bin/ls","ls","l",0);
printf("Estonoseejecuta!!!\n");
}

20.3fork()
Lafuncinintfork()cambiaunprocesonicoen2procesosidnticos,conocidoscomoel
padre(parent)yelhijo(child).Encasodexito,fork()regresa alprocesohijoyregresael
identificadordelprocesohijoalprocesopadre.Encasodefalla,fork()regresa
alproceso
padre,poneunvaloraerrno,ynosecreaunprocesohijo.
Elprocesohijotendrsupropioidentificadornico(PID).
Elsiguienteprogramailustraunejemplosencillodelusodefork,dondedoscopiassonhechasy
seejecutanjuntas(multitarea).
main()

{
intvalor_regr=0;

printf("Bifurcandoelproceso\n");
valor_regr=fork();
printf("Eliddelprocesoes%dyelvalorregresadoes%d\n",
getpid(),valor_regr);
execl("/bin/ls","ls","l",0);
printf("Estalineanoesimpresa\n");
}

Lasalidapodrasercomolasiguiente:
Bifurcandoelproceso
Eliddelprocesoes2662yelvalorregresadoes2663
Eliddelprocesoes2663yelvalorregresadoes0

Losprocesostienenunnicoidentificador,elcualserdiferenteencadaejecucin.
EsimposibleindicarconantelacincualprocesoobtendrelCPU.Cuandounprocesoesduplicado
en2procesossepuededetectarfcilmente(encadaproceso)sielprocesoeselhijooelpadreya
quefork()regresa paraelhijo.Sepuedenatraparcualquiererror,yaquefork()regresaun
,porejemplo:
intpid;/*identificadordelproceso*/
pid=fork();
if(pid<0)
{
printf("Nosepudoduplicar!!\n");
exit(1);
}
if(pid==0)
{
/*Procesohijo*/
......
}
else
{
/*Procesopadre*/
......
}

20.4wait()
Lafuncinintwait()(int*status)forzaraunprocesopadreparaqueespereaun
procesohijoquesedetengaotermine.LafuncinregresaelPIDdelhijoo
encasodeerrror.El
estadodelasalidadelhijoesregresadoenstatus.

20.5exit()
Lafuncinvoidexit(intstatus)terminaelprocesoquellamaaestafuncinyregresaen
lasalidaelvalordestatus.TantoUNIXylosprogramasbifurcadosdeCpuedenleerelvalorde
status.
Porconvencin,unestadode significaterminacinnormalycualquierotroindicaunerroroun
eventonousual.Muchasllamadasdelabibliotecaestndartienenerroresdefinidosenlacabecera
dearchivosys/stat.h.Sepuedefcilmentederivarsupropiaconvencin.
Unejemplocompletodeunprogramadebifurcacinsemuestraacontinuacin:
/*
fork.cejemplodeunprogramadebifurcacin
ElprogramapideelingresodecomandosdeUNIXquesondejadosenuna
cadena.Lacadenaesentonces"analizada"encontrandoblancos,etc
Cadacomandoysuscorrespondientesargumentossonpuestosen
unarreglodeargumentos,execvpesllamadaparaejecutarestoscomandos
enunprocesohijogeneradoporfork()
*/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
main()
{
charbuf[1024];
char*args[64];
for(;;)
{
/*
*Pideyleeuncomando.
*/
printf("Comando:");
if(gets(buf)==NULL)
{
printf("\n");
exit(0);
}
/*
*Dividirlacadenaenargumentos.
*/
parse(buf,args);
/*
*Ejecutarelcomando.
*/
ejecutar(args);
}
}
/*
*parsedivideelcomandoqueestaenbuf
*enargumentos.
*/
parse(char*buf,char**args)
{

while(*buf!=(char)NULL)
{
/*
*Quitarblancos.Usarnulos,paraque
*elargumentoprevioseaterminado
*automaticamente.
*/
while((*buf=='')||(*buf=='\t'))
*buf++=(char)NULL;

/*
*Guardarlosargumentos
*/
*args++=buf;

/*
*Brincarsobrelosargumentos.
*/
while((*buf!=(char)NULL)&&(*buf!='')&&(*buf!='\t'))
buf++;
}

*args=(char)NULL;
}
/*
*ejecutargeneraunprocesohijoyejecuta
*elprograma.
*/
ejecutar(char**args)
{
intpid,status;
/*
*Obtenerunprocesohijo.
*/
if((pid=fork())<0)
{
perror("fork");
exit(1);
/*NOTA:perror()generaunmensajedeerrorbreveenla
*salidadeerroresdescribiendoelultimoerrorencontrado
*duranteunallamadaalsistemaofunciondelabiblioteca.
*/
}
/*
*Elprocesohijoejecutaelcodigodentrodelif.
*/
if(pid==0)
{
execvp(*args,args);
perror(*args);
exit(1);
/*NOTA:lasversionesexecv()yexecvp()deexecl()sonutilescuando
elnumerodeargumentosesdesconocidopreviamente.
Losargumentosparaexecv()yexecvp()sonelnombredelarchivo
que
seraejecutadoyunvectordecadenasquecontienenlos
argumentos.
Elultimoargumentodecademadeberaserunapuntadora0(NULL)
execlp()yexecvp()sonllamadosconlosmismosargumentosque

execl()yexecv(),peroduplicanlasaccionesdelshellen
labusquedadeunarchivoejecutableenunlistadedirectorios.
Lalistadedirectoriosesobtenidadelambiente.
*/
}
/*
*Elpadreejecutaelwait.
*/
while(wait(&status)!=pid)
/*vacio*/;
}

20.6Ejercicios
1. CrearunprogramaenCendondeseuselafuncinpopen()paraentubarlasalidadel
comandorwhodeUNIXenelcomandomoredeUNIX.

Subsecciones

21.1ArchivosCabezera

21.2VariablesyFuncionesExternas

21.2.1Alcancedelasvariablesexternas

21.3VentajasdeUsarVariosArchivos

21.4Comodividirunprogramaenvariosarchivos

21.5OrganizacindelosDatosencadaArchivo

21.6LautileraMake

21.6.1ProgramandoMake

21.7CreacindeunArchivoMake(Makefile)

21.8UsodemacrosconMake

21.9Ejecucinde
Make

21.CompilacindeProgramasconArchivos
Mltiples
Enestecaptuloserevisalosaspectosteoricosyprcticosquenecesitanserconsideradoscuando
sonescritosprogramasgrandes.
Cuandoseescribenprogramasgrandessedeberprogramarenmdulos.Estossernarchivos
fuentesseparados.Lafuncinmain()deberestarenunarchivo,porejemploenmain.c,ylos
otrosarchivostendrnotrasfunciones.
Sepuedecrearunabibliotecapropiadefuncionesescribiendounasuitedesubrutinasenunooms
mdulos.Dehecholosmdulospuedensercompartidosentremuchosprogramassimplemente
incluyendolosmdulosalcompilarcomoseveracontinuacin.
Setienevariasventajassilosprogramassonescritosdeestaforma:

losmdulosdeformanaturalsedividirnengruposcomunesdefunciones.
sepuedecompilarcadamdulosseparadamenteyligarloconlosmdulosyacompilados.
lasutilerastalescomomakenosayudanamantenersistemasgrandes.

21.1ArchivosCabezera
Siseadoptaelmodelomodularentoncessequerrtenerparacadamdulolasdefinicionesdelas
variables,losprototiposdelasfunciones,etc.Sinembargo,qusucedesivariosmdulosnecesitan
compartirtalesdefiniciones?Entalcaso,lomejorescentralizarlasdefinicionesenunarchivo,y
compartirelarchivoentrelosmdulos.Talarchivoesusualmentellamadounarchivocabecera.
Porconvencinestosarchivostienenelsufijo.h
Sehanrevisadoyaalgunosarchivoscabeceradelabibliotecaestndar,porejemplo:
#include<stdio.h>

Sepuedendefinirlospropiosarchivoscabeceraysepuedenincluirenelprogramacomosemuestra
enseguida:
#include"mi_cabecera.h"

Losarchivoscabeceraporlogeneralslocontienendefinicionesdetiposdedatos,prototiposde
funcionesycomandosdelpreprocesadordeC.
Considerarelsiguienteprogramadeejemplo:
main.c
/*
*main.c
*/
#include"cabecera.h"
#include<stdio.h>
char*Otra_cadena="HolaaTodos";
main()
{
printf("Ejecutando...\n");
/*
*LlamaraEscribirMiCadena()definidaenotroarchivo
*/
EscribirMiCadena(MI_CADENA);
printf("Terminado.\n");
}

EscribirMiCadena.c
/*
*EscribirMiCadena.c
*/
externchar*Otra_cadena;
voidEscribirMiCadena(EstaCadena)
char*EstaCadena;
{
printf("%s\n",EstaCadena);

printf("VariableGlobal=%s\n",Otra_cadena);
}

cabecera.h
/*
*cabecera.h
*/
#defineMI_CADENA"HolaMundo"
voidEscribirMiCadena();

Cadamdulosercompiladoseparadamentecomosevermsadelante.
Algunosmdulostienenladirectivadepreprocesamiento#include"cabecera.h"yaque
compartendefinicionescomunes.Algunoscomomain.ctambinincluyenarchivoscabecera
estndar.Lafuncinmain.cllamaalafuncinEscribirMiCadena()lacualestaenel
mdulo(archivo)EscribirMiCadena.c
ElprototipovoiddelafuncinEscribirMiCadenaestadefinidaencabecera.h.
Observarqueengeneralsedebedecidirentretenerunmdulo.cquetengaaccesosolamenteala
informacinquenecesitaparasutrabajo,conlaconsecuenciademantenermuchosarchivos
cabeceraytenerprogramasdetamaomoderadoconunoodosarchivoscabecera(probablemente
lomejor)quecompartanmsdefinicionesdemdulos.
Unproblemaquesetienealemplearmdulossonelcompartirvariables.Sisetienenvariables
globalesdeclaradasysoninstanciadasenunmdulo,cmopuedenserpasadasaotrosmdulos
paraqueseanconocidas?
Sepodranpasarlosvalorescomoparmetrosalasfunciones,pero:

puedeserestolaboriososisepasanlosmismosparmetrosamuchasfuncionesosilalista
deargumentosesmuylarga.
arreglosyestructurasmuygrandessondifcilesdeguardarlocalmenteproblemasde
memoriaconelstack.

21.2VariablesyFuncionesExternas
Lasvariablesyargumentosdefinidosdentrodelasfuncionesson``internas'',esdecir,locales.
Lasvariables``externas''estndefinidasfueradelasfuncionesseencuentranpotencialmente
disponiblesatodoelprograma(globales)peroNOnecesariamente.Lasvariablesexternasson
siemprepermanentes.
EnellenguajeC,todaslasdefinicionesdefuncionessonexternas,NOsepuedentener
declaracionesdefuncionesanidadascomoenPASCAL.

21.2.1Alcancedelasvariablesexternas
Unavariableexterna(ofuncin)noessiempretotalmenteglobal.EnellenguajeCseaplicala
siguienteregla:
Elalcancedeunavariableexterna(ofuncin)iniciaenelpuntodedeclaracinhastaelfindel
archivo(mdulo)dondefuedeclarada.
Considerarelsiguientecdigo:
main()
{...}
intque_alcance;
floatfin_de_alcance[10];
voidque_global()
{...}
charsolitaria;
floatfn()
{...}

Lafuncinmain()nopuedeveralasvariablesque_alcanceofin_de_alcance,perolas
funcionesque_global()yfn()sipueden.Solamentelafuncinfn()puedevera
solitaria.
Estaestambinunadelasrazonesporlasquesedebenponerlosprototiposdelasfuncionesantes
delcuerpodelcdigo.
Porloqueenelejemplolafuncinmainnoconocernadaacercadelasfunciones
que_global()yfn().Lafuncinque_global()nosabenadaacercadelafuncinfn(),
perofn()sisabeacercadelafuncinque_global(),yaqueestaaparecedeclarada
previamente.
Laotraraznporlacualseusanlosprototiposdelasfuncionesespararevisarlosparmetrosque
sernpasadosalasfunciones.
Siserequierehacerreferenciaaunavariableexternaantesdequeseadeclaradaoqueestadefinida
enotromdulo,lavariabledebeserdeclaradacomounavariableexterna,porejemplo:
externintque_global;

Regresandoalejemplodeprogramacinmodular,setieneunaarreglodecaracterestipoglobal
Otra_cadenadeclaradoenmain.cyqueestacompartidoconEscribirMiCadenadondeesta
declaradacomoexterna.
Sedebetenercuidadoconelespecificadordealmacenamientodeclaseyaqueelprefijoesuna
declaracin,NOunadefinicin,estoes,nosedaalmacenamientoenlamemoriaparaunavariable
externasolamenteledicealcompiladorlapropiedaddelavariable.Lavariableactualslodeber
estardefinidaunavezentodoelprogramasepuedentenertantasdeclaracionesexternascomose
requieran.

Lostamaosdelosarreglosdebernserdadosdentrodeladeclaracin,peronosonnecesariosen
lasdeclaracionesexternas,porejemplo:
main.cintarr[100];
arch.cexternintarr[];

21.3VentajasdeUsarVariosArchivos
Lasventajasprincipalesdedispersarunprogramaenvariosarchivosson:

Equiposdeprogramadorespuedentrabajarenelprograma,cadaprogramadortrabajaenun
archivodiferente.
Puedeserusadounestiloorientadoaobjetos.Cadaarchivodefineuntipoparticularde
objetocomountipodedatoylasoperacioneseneseobjetocomofunciones.La
implementacindelobjetopuedemantenerseprivadoalrestodelprograma.Conloanterior
selogranprogramasbienestructuradosloscualessonfcilesdemantener.
Losarchivospuedencontenertodaslasfuncionesdeungruporelacionado,porejemplo
todaslasoperacionesconmatrices.Estaspuedenseraccesadascomounafuncindeuna
biblioteca.
Objetosbienimplementadosodefinicionesdefuncionespuedenserreusadasenotros
programas,conloquesereduceeltiempodedesarrollo.
Enprogramasmuygrandescadafuncinprincipalpuedeocuparunpropioarchivo.
Cualquierotrafuncindebajonivelusadaenlaimplemantacinpuedeserguardadaenel
mismoarchivo,porloquelosprogramadoresquellamenalafuncinprincipalnose
distraernporeltrabajodebajonivel.
Cuandoloscambiossonhechosaunarchivo,solamenteesearchivonecesitaser
recompiladoparareconstruirelprograma.LautileramakedeUNIXesmuytilpara
reconstruirprogramasconvariosarchivos.

21.4Comodividirunprogramaenvarios
archivos
Cuandounprogramaesseparadoenvariosarchivos,cadaarchivocontendrunaomsfunciones.
Unarchivoincluirlafuncinmain()mientraslosotroscontendrnfuncionesquesernllamados
porotros.Estosotrosarchivospuedensertratadoscomofuncionesdeunabiblioteca.
Losprogramadoresusualmenteiniciandiseandounprogramadividiendoelproblemaensecciones
msfcilmentemanejables.Cadaunadeestasseccionespodrnserimplementaddascomounao
msfunciones.Todaslasfuncionesdecadaseccinporlogeneralestarnenunsloarchivo.
Cuandosehaceunaimplementacintipoobjetodelasestructurasdedatos,esusualtenertodaslas
funcionesqueaccesanseobjetoenelmismoarchivo.Lasventajasdeloanteriorson:

Elobjetopuedeserfcilmentereusadoenotrosprogramas.

Todaslasfuncionesrelacionadasestanguardadasjuntas.
Losltimoscambiosalobjetorequierensolamentelamodificacindeunarchivo.

Elarchivocontieneladefinicindeunobjeto,ofuncionesqueregresasanvalores,hayuna
restriccinenlallamadadeestasfuncionesdesdeotroarchivo,almenosqueladefinicindelas
funcionesestnenelarchivo,noserposiblecompilarcorrectamente.
LamejorsolucinaesteproblemaesescribirunarchivocabeceraparacadaarchivodeC,estos
tendrnelmismonombrequeelarchivodeC,peroterminarnen.h.Elarchivocabeceracontiene
lasdefinicionesdetodaslasfuncionesusadasenelarchivodeC.
CuandounafuncinenotroarchivollameunafuncindenuestroarchivodeC,sepuededefinirla
funcinusandoladirectiva#includeconelarchivoapropiado.h

21.5OrganizacindelosDatosencada
Archivo
Cualquierarchivodebertenersusdatosorganizadosenunciertoorden,tipcamentepodrserla
siguiente:

Unprembuloconsistentedelasdefinicionesdeconstantes(#define),cabecerasde
archivos(#include)ylostiposdedatosimportantes(typedef).
Declaracindevariablesglobalesyexternas.Lasvariablesglobalespodranestar
inicializadasaqu.
Unaomsfunciones.

Elordenanterioresimportanteyaquecadaobjetodeberestardefinidoantesdequepuedaser
usado.Lasfuncionesqueregresanvaloresdebernestardefinidosantesdequeseanllamados.Esta
definicinpodraserunadelassiguientes:

Ellugarenquelafuncinestadefinidayllamadaenelmismoarchivo,unadeclaracin
completadelafuncinpuedesercolocadadelantedecualquierllamadadelafuncin.
Silafuncinesllamadadesdeunarchivodondenoestadefinida,unprototipodeber
aparecerantesquellamadadelafuncin.

Unafuncindefinidacomo:
floatenc_max(floata,floatb,floatc)
{...}

podrtenerelsiguienteprototipo:
floatenc_max(floata,floatb,floatc);

Elprototipopuedeaparecerentrelasvariablesglobaleseneliniciodelarchivofuente.
Alternativamentepuedeserdeclaradoenelarchivocabeceraelcualesledousandoladirectiva
#include.

EsimportanterecordarquetodoslosobjetosenCdebernestardeclaradosantesdeserusados.

21.6LautileraMake
LautileraMakeesunmanejadorinteligentedeprogramasquemantienelaintegridaddeuna
coleccindemdulosdeunprograma,unacoleccindeprogramasounsistemacompletono
tienenqueserprogramas,enlaprcticapuedesercualquiersistemadearchivos(porejemplo,
captulosdetextodeunlibroqueestasiendotipografiado).Suusoprincipalhasidoenlaasistencia
deldesarrollodesistemasdesoftware.
EstautilerafueinicialmentedesarrolladaparaUNIX,peroactualmenteestadisponibleenmuchos
sistemas.
Observarquemakeesunaherramientadelprogramador,ynoespartedellenguajeCodealguno
otro.
Supongamoselsiguienteproblemademantenimientodeunacoleccingrandedearchivosfuente:
main.cf1.c......fn.c

Normalmentesecompilarnlosarchivosdelasiguientemanera:
gccomainmain.cf1.c.......fn.c

Sinembargosisesabequealgunosarchivoshansidocompiladospreviamenteysusarchivosfuente
nohansidocambiadosdesdeentonces,entoncessepuedeahorrartiempodecompilacinligando
loscdigosobjetosdeestosarchivos,esdecir:
gccomainmain.cf1.c...fi.o...fj.o...fn.c

SepuedeusarlaopcincdelcompiladordeCparacrearuncdigoobjeto(.o)paraunmdulo
dado.Porejemplo:
gcccmain.c

quecrearunarchivomain.o.Noserequiereproporcionarningunaligadealgunabibliotecaya
queserresueltaenlaetapadeligamiento.
Setieneelproblemaenlacompilacindelprogramadesermuylarga,sinembargo:

Seconsumetiempoalcompilarunmdulo.csielmdulohasidocompiladoantesyno
hasidomodificadoelarchivofuente,porlotantonohaynecesidadderecompilarlo.Se
puedesolamenteligarlosarchivosobjeto.Sinembargo,noserfcilrecordarcuales
archivoshansidoactualizados,porloquesiligamosunarchivoobjetonoactualizado,el
programaejecutablefinalestarincorrecto.

Cuandosetecleaunasecuencialargadecompilacinenlalneadecomandossecometen
erroresdetecleo,obien,setecleaenformaincompleta.Existirnvariosdenuestrosarchivos
quesernligadosaligualquearchivosdebibliotecasdelsistema.Puedeserdifcilrecordar
lasecuenciacorrecta.

Siseusalautileramaketodoestecontroleshechoconcuidado.Engeneralslolosmdulosque
seanmsviejosquelosarchivosfuentesernrecompilados.

21.6.1ProgramandoMake
Laprogramacindemakeesdirecta,basicamenteseescribeunasecuenciadecomandosque
describecomonuestroprograma(osistemadeprogramas)serconstrudoapartirdelosarchivos
fuentes.
Lasecuenciadeconstrucinesdescritaenlosarchivosmakefile,loscualescontienenreglasde
dependenciayreglasdeconstruccin.
Unaregladedependenciatienedospartesunladoizquierdoyunladoderechoseparadospor:
ladoizquierdo:ladoderecho

Elladoizquierdodaelnombredeldestino(losnombresdelprogramaoarchivosdelsistema)que
serconstrudo(target),mientraselladoderechodalosnombresdelosarchivosdeloscuales
dependeeldestino(porejemplo,archivosfuente,archivoscabecera,archivosdedatos).
Sieldestinoestafueradefechaconrespectoalaspartesqueleconstituyen,lasreglasde
construccinsiguiendolasreglasdedependenciasonusadas.
PorlotantoparaunprogramatpicodeCcuandounarchivomakeesejecutadolassiguientes
tareassonhechas:
1. Elarchivomakeesledo.ElMakefileindicacualesobjetosyarchivosdebibliotecase
requierenparaserligadosycualesarchivoscabecerayfuentenecesitansercompiladospara
crearcadaarchivoobjeto.
2. Lahoraylafechadecadaarchivoobjetosonrevisadoscontraelcdigofuenteylosarchivos
cabeceradeloscualesdependen.Sicualquierfuenteoarchivocabecerasonmsrecientes
queelarchivoobjeto,entonceslosarchivoshansidomodificadosdesdelaltima
modificacinyporlotantolosarchivosobjetonecesitanserrecompilados.
3. Unavezquetodoslosarchivosobjetoshansidorevisados,eltiempoylafechadetodoslos
archivosobjetosonrevisadoscontralosarchivosejecutables.Siexistearchivosejecutables
viejossernrecompilados.
Observarquelosarchivosmakepuedenobedecercualquiercomandoqueseatecleadoenlalnea
decomandos,porconsiguientesepuedenusarlosarchivosmakeparanosolamentecompilar
archivos,sinotambinparahacerrespaldos,ejecutarprogramassilosarchivosdedatoshansido
cambiadosolimpiezadedirectorios.

21.7CreacindeunArchivoMake(Makefile)
Lacreacindelarchivoesbastantesimple,secreaunarchivodetextousandoalgneditordetextos.
ElarchivoMakefilecontienesolamenteunalistadedependenciasdearchivosycomandosqueson
necesariosparasatisfacerlos.
Semuestraacontinuacinunejemplodeunarchivomake:
prog:prog.of1.of2.o
gccoprogprog.of1.of2.olm...
prog.o:cabecera.hprog.c
gcccprog.c
f1.o:cabecera.hf1.c
gcccf1.c
f2.o:....
...

Lautileramakelointerpretardelasiguienteforma:
1. progdependedetresarchivos:prog.o,f1.oyf2.o.Sicualquieradelosarchivos
objetohacambiadodesdelaltimacompilacinlosarchivosdebenserreligados.
2. prog.odependede2archivos,siestoshancambiadoprog.odeberserrecompilado.Lo
mismosucedeconf1.oyf2.o.
Losltimos3comandosenmakefilesonllamadosreglasexplcitasyaquelosarchivosenlos
comandossonlistadospornombre.
Sepuedenusarreglasimplcitasenmakefileparageneralizarreglasyhacermscompactala
escritura.
Sisetiene:
f1.o:f1.c
gcccf1.c
f2.o:f2.c
gcccf2.c

sepuedegeneralizara:
.c.o:gccc$<

Locualseleecomo.ext_fuente.ext_destino:comandodonde$<esunaformabreve
paraindicarlosarchivosquetienenlaextensin.c
SepuedeninsertarcomentariosenunMakefileusandoelsmbolo#,endondetodoslos
caracteresquesiguena#sonignorados.

21.8UsodemacrosconMake
Sepuedendefinirmacrosparaqueseanusadaspormake,lascualessontipcamenteusadaspara
guardarnombresdearchivosfuente,nombresdearchivosobjeto,opcionesdelcompiladoroligasde
bibliotecas.
Sedefinenenunaformasimple,porejemplo:
FUENTES=main.cf1.cf2.c
CFLAGS=ggdbC
LIBS=lm
PROGRAMA=main
OBJETOS=(FUENTES:.c=.o)

endonde(FUENTES:.c=.o)cambialaextensin.cdelosfuentesporlaextensin.o
Parareferirseousarunamacroconmakesedebehacer$(nomb_macro),porejemplo:
$(PROGRAMA):$(OBJETOS)
$(LINK.C)o$@$(OBJETOS)$(LIBS)

Enelejemplomostradoseobservaque:

Lalneaquecontiene$(PROGRAMA):$(OBJETOS)generaunalistadedependencias
yeldestino.
Seempleanmacrosinternascomo$@.

Existenvariasmacrosinternasacontinuacinsemuestranalgunasdeellas:
$*
$@
$

Partedelnombredelarchivodeladependenciaactualsinelsufijo.
Nombrecompletodeldestinoactual.
Archivo.cdeldestino

Unejemplodeunmakefileparaelprogramamodulardiscutidopreviamentesemuestraa
continuacin:
#
#Makefile
#
FUENTES.c=main.cEscribirMiCadena.c
INCLUDES=
CFLAGS=
SLIBS=
PROGRAMA=main
OBJETOS=$(FUENTES.c:.c=.o)
#Destino(target)especial(iniciacon.)
.KEEP_STATE:
debug:=CFLAGS=ggdb

alldebug:$(PROGRAMA)
$(PROGRAMA):$(INCLUDES)$(OBJETOS)
$(LINK.c)o$@$(OBJETOS)$(SLIBS)
clean:
rmf$(PROGRAMA)$(OBJETOS)

ParavermsinformacindeestautileradentrodeLinuxusarinfomake

21.9EjecucindeMake
Parausarmakesolamentesedeberteclearenlalneadecomandos.Elsistemaoperativo
automticamentebuscaunarchivoconelnombreMakefile(observarquelaprimeraletraes
maysculayelrestominsculas),porlotantosisetieneunarchivoconelnombreMakefileyse
tecleamakeenlalneadecomandos,elarchivoMakefiledeldirectorioactualserejecutado.
Sepuedeanularestabsquedadeestearchivotecleandomakefmakefile.
Existenalgunasotrasopcionesparamakelascualespuedenserconsultadasusandoman.

Subsecciones

22.1EntubandoenunprogramadeC<stdio.h>

22.1.1

popen()

Tuberaformateada

22.1.2

pipe()

Tuberadebajonivel

22.Comunicacinentreprocesos(IPC
InterprocessCommunication),PIPES
Acontinuacinseiniciarlarevisindecomomltiplesprocesospuedenestarsiendoejecutadosen
unamquinayquizssiendocontrolados(generadosporlafuncinfork())porunodenuestros
programas.
Ennumerosasaplicacioneshayunanecesidadclaraparaqueestosprocesossecomuniquenparael
intercambiodedatosoinformacindecontrol.Hayunoscuantosmtodosparahacerloanterior.Se
puedenconsiderarlossiguientes:

Tubera(Pipes)
Seales(Signals)
ColasdeMensajes
Semforos
MemoriaCompartida
Sockets

Enestecaptuloseestudiaelentubamientodedosprocesos,enlossiguientescaptulosserevisan
losotrosmtodos.

22.1EntubandoenunprogramadeC
<stdio.h>
Elentubamientoesunprocesodondelaentradadeunprocesoeshechaconlasalidadeotro.Seha
vistoejemplosdeloanteriorenlalneadecomandosdeUnixcuandoseusaelsmbolo|.
SevercomohacerloanteriorenunprogramadeCteniendodos(oms)procesosdivididos.Lo
primeroquesedebehaceresabrirunatubera,enUnixpermitedosformasdehacerlo:

22.1.1popen()Tuberaformateada
FILE*popen(char*orden,char*tipo)AbreunatuberadeE/Sdondeelcomandoes

elprocesoqueserconectadoalprocesoqueloestallamandodeestaformacreandoelpipe.Eltipo
es"r"paralectura,o"w"paraescritura.
Lafuncinpopen()regresaunapuntadoraunflujooNULLparaalgntipodeerror.
Unatuberaabiertaconpopen()debersiemprecerrarseconpclose(FILE*flujo).
Seusafprintf()yfscanf()paracomunicarseconelflujodelatubera.

22.1.2pipe()Tuberadebajonivel
intpipe(intdescf[2])Creaunpardedescritoresdearchivo,queapuntanaunnodoide
unatubera,ylosponeenelvectordedoselementosapuntadopordescf.descf[0]espara
lecturaydescf[1]esparaescritura.
pipe()regresa0encasodexito,yencasodeerrorsedevuelve1yseponeunvalorapropiado
enerrno.
Elmodelodeprogramacinestndaresqueunavezquelatuberahasidopuesta,dos(oms)
procesoscooperativosserncreadospordivisinylosdatossernpasadosempleandoread()y
write().
Lastuberasabiertasconpipe()debernsercerradasconclose(intfd).Acontinuacinse
muestraunejemplodeentubamientoqueseutilizaparaestarenviandodatosalprograma
gnuplot,empleadoparagraficar.Ladescripcindelasfuncionesdelosmduloseslasiguiente:

Elprogramatienedosmdulos,grafica.cquecontienelafuncinmain()y
graficador.cquecontienelasrutinasparaenviarlosdatosalprogramagnuplot.
Elprogramasuponequesetieneinstaladoelprogramadegraficacingnuplotenel
directorio/usr/bin.
Elprogramagrafica.cllamaalprogramagnuplot.
Dosflujossongeneradosusandoelprogramagrafica.c,enunodeellossegrficala
funciny=0.5ey=aleat(01.0)yenelotrolasfuncionesy=sen(x)e
y=sen(1/x).
Dostuberassoncreadascadaunaconunflujodedatos.
Gnuplotgeneraen``vivo''lasalidadelasgrficas.

Ellistadodelcdigoparagrafica.ceselsiguiente:
/*grafica.c
*Ejemplodelatuberias(pipe)deUnix.Sellamaalpaquete"gnuplot"
*paragraficardesdeunprogramaenC.
*Lainformacionesentubadaagnuplot,secrean2tuberias,unadibujarala
*graficadey=0.5ey=random01.0,laotragraficaray=sen(1/x)ey=senx
*/
#include"externals.h"
#include<signal.h>
#defineDEG_TO_RAD(x)(x*180/M_PI)
voidsalir();

FILE*fp1,*fp2,*fp3,*fp4;
main()
{
floati;
floaty1,y2,y3,y4;
/*abrirarchivosenloscualesseguardaranlosdatosagraficar*/
if(((fp1=fopen("plot11.dat","w"))==NULL)||
((fp2=fopen("plot12.dat","w"))==NULL)||
((fp3=fopen("plot21.dat","w"))==NULL)||
((fp4=fopen("plot22.dat","w"))==NULL))
{printf("Errornosepuedeabrirunoovariosarchivosde
datos\n");
exit(1);
}

signal(SIGINT,salir);/*Atraparlallamadadelafunciondesalidactrlc
*/
IniciarGraf();
y1=0.5;
srand48(1);/*ponersemilla*/
for(i=0;;i+=0.01)/*incrementarisiempre*/
{/*usarctrlcparasalirdelprograma*/
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));

/*cargararchivos*/
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);

/*asegurarsequelosbufferssoncopiadosaldisco*/
/*paraquegnuplotpuedaleerlosdatos*/
fflush(fp1);
fflush(fp2);
fflush(fp3);
fflush(fp4);

/*graficaralotgraph*/
Graf1Vez();
usleep(10000);/*dormirporuncortotiempo(250microsegundos)*/
}
}
voidsalir()
{
printf("\nctrlcatrapada:\nTerminandolastuberias\n");
PararGrafica();

printf("Cerrandolosarchivosdedatos\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
fclose(fp4);

printf("Borrandolosarchivosdedatos\n");
BorrarDat();
}

Elmdulograficador.ceselsiguiente:
/**********************************************************************/
/*modulo:graficador.c*/
/*Contienerutinasparagraficarunarchivodedatosproducidopor*/
/*programa.Enestecasosegraficaendosdimensiones*/
/**********************************************************************/
#include"externals.h"
staticFILE*plot1,
*plot2,
*ashell;
staticchar*iniciargraf1="plot[][0:1.1]'plot11.dat'withlines,
'plot12.dat'withlines\n";
staticchar*iniciargraf2="plot'plot21.dat'withlines,'plot22.dat'with
lines\n";
staticchar*comando1="/usr/bin/gnuplot>dump1";
staticchar*comando2="/usr/bin/gnuplot>dump2";
staticchar*borrarchivos="rmplot11.datplot12.datplot21.datplot22.dat";
staticchar*set_term="setterminalx11\n";
voidIniciarGraf(void)
{
plot1=popen(comando1,"w");
fprintf(plot1,"%s",set_term);
fflush(plot1);
if(plot1==NULL)
exit(2);
plot2=popen(comando2,"w");
fprintf(plot2,"%s",set_term);
fflush(plot2);
if(plot2==NULL)
exit(2);
}
voidBorrarDat(void)
{
ashell=popen(borrarchivos,"w");
exit(0);
}
voidPararGrafica(void)
{
pclose(plot1);
pclose(plot2);
}
voidGraf1Vez(void)
{
fprintf(plot1,"%s",iniciargraf1);
fflush(plot1);
fprintf(plot2,"%s",iniciargraf2);
fflush(plot2);
}

Elarchivodecabeceraexternals.hcontienelosiguiente:
/*externals.h*/
#ifndefEXTERNALS
#defineEXTERNALS

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
/*prototipos*/

Conlafinalidaddetenerunmejorcontrolenlacompilacindelprogramaseluedeusarelsiguiente
archivoMakefile:
FUENTES.c=grafica.cgraficador.c
INCLUDES=
CFLAGS=
SLIBS=lm
PROGRAMA=grafica
OBJETOS=$(FUENTES.c:.c=.o)
$(PROGRAMA):$(INCLUDES)$(OBJETOS)
gcco$(PROGRAMA)$(OBJETOS)$(SLIBS)
grafica.o:externals.hgrafica.c
gcccgrafica.c
graficador.o:externals.hgraficador.c
gcccgraficador.c
clean:
rmf$(PROGRAMA)$(OBJETOS)

Subsecciones

23.1Creacinynombradodesockets

23.2Conectandosocketsdeflujo

23.2.1Transferenciadedatosenunflujoycerrado

23.Sockets
Lossocketsproporcionanunacomunicacindedosvas,puntoapuntoentredosprocesos.Los
socketssonmuyverstilesysonuncomponentebsicodecomunicacinentreinterprocesose
intersistemas.Unsocketesunpuntofinaldecomunicacinalcualsepuedeasociarunnombre.Este
tieneuntipoyunoomsprocesosasociados.
Lossocketsexistenenlosdominiosdecomunicacin.Unsocketdedominioesunarepresentacin
quedaunaestructuradedireccionamientoyunconjuntodeprotocolos.Lossocketsseconectan
solamenteconsocketsenelmismodominio.Veintitrsdominiosdesocketssonidentificados(ver
<sys/socket.h>),deloscualessolamentelosdominiosdeUNIXeInternetsonnormalmente
socketsdeLinuxusadosparacomunicarseentreprocesosenunslosistema,comootrasformasde
comunicacinentreprocesos.
EldominiodeUNIXdaunespaciodedireccionesdesocketenunsistema.Lossocketsdedominio
deUNIXsonnombradosconlasrutasdeUNIX.Lossocketspuedentambinserusadospara
comunicarprocesosentrediferentessistemas.Elespaciodedireccionesdelsocketentrelossistemas
conectadosesllamadoeldominiodeInternet.
LacomunicacindeldominiodeInternetusalasuitedelprotocolodeInternetTCP/IP.
Lostiposdesocketdefinenlaspropiedadesdecomunicacinvisiblesparalaaplicacin.Los
procesossecomunicansolamenteentrelossocketsdelmismotipo.Existencincotiposdesockets.
Socketdeflujo
daunflujodedatosdedosvas,confiable,ysinduplicadossinlmitesdegrabacin.Elflujo
operaenformaparecidaaunaconversacintelefnica.EltipodelsocketesSOCK_STREAM,
elcualeneldominiodeInternetusaTCP(TransmissionControlProtocol).
Socketdedatagrama
soportaunflujodemensajesdedosvas.Enunsocketdedatagramapodrarecibirmensajes
endiferenteordendelasecuenciadelacuallosmensajesfueronenvados.Loslmitesde
grabacinenlosdatossonpreservados.Lossocketsdedatagramaoperanparecidosapasar
cartashaciaadelanteyhaciaatrsenelcorreo.EltipodesocketesSOCK_DGRAM,elcual
eneldominiodeinternetusaUDP(UserDatagramProtocol).
Socketdepaquetesecuencial
daunaconexindedosvas,secuencialyconfiableparadatagramasdeunalongitudfija

mxima.EltipodesocketesSOCK_SEQPACKET.Nohayprotocoloimplementadoparaeste
tipodecualquierfamiliadeprotocolos.
rawsocket
daaccesoalosprotocolosdecomunicacinsubyacente.
Lossocketssonusualmentedatagramasorientados,perosuscaractersticasexactasdependendela
interfazdadaporelprotocolo.

23.1Creacinynombradodesockets
Sellamaalafuncinintsocket(intdominio,inttipo,intprotocolo);para
crearunextremodeunacomunicacin(socket)eneldominioespecificadoydeltipoindicado.Si
unprotocolonoesespecificado.elsistemausaunopredefinidoquesoporteeltipodesocket
especificado.Elmanejadordelsocket(undescriptor)esdevuelto.Unprocesoremotonotiene
formadeidentificarunsockethastaqueunadireccinseligadaaeste.Losprocesosde
comunicacinseconectanatravsdedirecciones.EneldominiodeUNIX,unaconexinesta
compuestausualmentedeunoodosnombresderutas.EneldominiodeInternet,unaconexinesta
compuestadedireccioneslocalesyremotasyparteslocalesyremotas.Enmuchosdominios,las
conexionesdebensernicas.
Sellamaalafuncinintbind(intsockfd,structsockaddr*nomb,
socklen_tlongdir)paraenlazaruncaminoounadireccindeInterneaunconector
(socket).Haytresformasdiferentesdellamarabind(),dependiendodeldominiodelsocket.

ParalossocketsdeldominiodeUNIXconrutasconteniendo14,omenoscaracteresse
puedeusar:
#include<sys/socket.h>
...
bind(sd,(structsockaddr*)&direccion,longitud);

SilatrayectoriadeunsocketdeldominiodeUNIXrequieresmscaracteres,usar:
#include<sys/un.h>
...
bind(sd,(structsockaddr_un*)&direccion,longitud);

ParasocketsdeldominiodeInternetusar:
#include<net/netinet.h>
...
bind(sd,(structsockaddr_in*)&direccion,longitud);

EneldominiodeUNIX,elenlazadodenombrescreaunsocketconnombreenelsistemade
archivos.Usarunlink()orrm()paraeliminarelsocket.

23.2Conectandosocketsdeflujo
Laconexindesocketsesusualmenteasimtrica.Unprocesousualmenteactacomounservidory
elotroprocesoeselcliente.Elservidorenlazasusocketauncaminoodireccinpreviamente
acordada,yentoncesbloqueaelsocket.ParaunconetorSOCK_STREAM,elservidorllamaala
funcinintlisten(ints,intbacklog),paraindicarcuantaspeticionesdeconexin
sernpuestasenlacola.Unclienteinicialaconexinalsocketdelservidormedianteunallamadaa
lafuncinintconnect(insts,structsockaddr*nomb_serv,int
longdirec).UnallamadaeneldominiodeUNIXescomolasiguiente:
structsockaddr_unserver;
...
connect(sd,(strucsockaddr_un*)&server,long);

mientraseneldominiodeInternetlallamadapodraser:
structsockaddr_inserver;
...
connect(sd,(strucsockaddr_un*)&server,long);

Sielsocketdelclientenoestaenlazadoalmomentodehacerlallamadaparalaconexin,elsistema
automticamenteseleccionayligaunnombrealsocket.ParaunsocketSOCK_STREAM,el
servidorllamaalafuncinaccept()paracompletarlaconexin.
Lafuncinintaccept(ints,structsockaddr*addr,int*longdirec)
regresaunconectornuevoelcualesvlidosolamenteparalaconexinparticular.Unservidor
puedetenermltiplesconexionesSOCK_STREAMactivasalmismotiempo.

23.2.1Transferenciadedatosenunflujoycerrado
SeempleanvariasfuncionesparaenviaryrecibirdatosdeunsocketSOCK_STREAM.Estasson
write(),read(),intsend(ints,constvoid*msg,size_tlon,int
flags),yintrecv(ints,void*buf,size_tlon,intflags).Las
funcionessend()yrecv()sonparecidasaread()ywrite(),perotienenalgunasbanderas
operacionalesadicionales.
ElargumentoflagsdeunallamadaarecvseformaaplicandoeloperadordebitsOlgicoaunoo
msdelosvaloressiguientes:
MSG_OOB
Pidelarecepcindedatosfueradebandaquenoserecibiranenelflujodedatosnormal.
Algunosprotocolosponendatosdespachadosconprontitudenlacabezadelacoladedatos
normales,yas,estaopcinnopuedeemplearsecontalesprotocolos.
MSG_PEEK
Hacequelaoperacinderecepcindevuelvadatosdelprincipiodelacoladerecepcinsin
quitarlosdeall.As,unaprximallamadaderecepcindevolverlosmismosdatos.
MSG_WAITALL

Estaopcinhacequelaoperacinsebloqueehastaquesesatisfagalapeticin
completamente.Sinembargo,lallamadapuedeaundevolvermenosdatosdelospedidossise
capturaunaseal,siocurreunerrorounadesconexin,osilosprximosdatosquesevana
recibirsondeuntipodiferentedelquesehadevuelto.
MSG_NOSIGNAL
EstaopcindesactivaelqueseproduzcaunasealSIGPIPEsobrelosconectoresorientadosa
conexincuandoelotroextremodesaparece.
MSG_ERRQUEUE
Estaopcinindicaqueloserroresencoladosdebenrecibirsedesdelacoladeerroresde
conectores.Elerrorsepasaenunmensajeauxiliarconuntipodependientedelprotocolo
(paraIPv4steesIP_RECVERR).Elusuariodebeproporcionaunbufferdetamaosuficiente.
Veacmsg(3)paraobtenermsinformacinsobremensajesauxiliares.

Sobreestedocumento...
ManualdeC
ThisdocumentwasgeneratedusingtheLaTeX

2HTML

translatorVersion200221(1.70)
Copyright1993,1994,1995,1996,NikosDrakos,ComputerBasedLearningUnit,Universityof
Leeds.
Copyright1997,1998,1999,RossMoore,MathematicsDepartment,MacquarieUniversity,
Sydney.
Thecommandlineargumentswere:
latex2htmlmanual
ThetranslationwasinitiatedbyHctorTejedaVon20050812

También podría gustarte