· web viewes un área muy importante manejada directamente por la ucp para alojar datos durante...

69
1.1 Introducción a la POO §1 Qué es eso de los "Objetos"? En la programación tradicional existía una clara diferenciación entre los datos y su manipulación, es decir, el conjunto de algoritmos para manejarlos. Los tipos de datos eran muy simples; todo lo más números de diverso tipo y caracteres (aislados o agrupados en cadenas o matrices), pero nunca elementos heterogéneos. La situación para el programador era que el lenguaje parecía decirle: estos son los posibles contenedores para la información que debes manejar (los tipos de datos soportados por el lenguaje) y aquí aparte, las operaciones que puedes realizar con ellos (las operaciones definidas para dichos datos). Por ejemplo, si son datos numéricos las operaciones aritméticas, las comparaciones, las asignaciones, etc. Con estas herramientas el programador construía su código, y para poner un poco de orden en la maraña de algoritmos solo tenía el recurso de agruparlo en funciones. Si se tenía que hacer un programa de gestión comercial, la información correspondiente a un concepto más o menos real, por ejemplo un "cliente", tenía que ser desmenuzada en una serie de datos aislados: nombre, domicilio, población, provincia, teléfono, condiciones de compra, saldo, tipo de descuento, número de vendedor asignado, fecha de última compra, etc. etc. Luego, para hacer una factura, todos estos elementos eran tomados y procesados individualmente. Un primer intento de construir tipos de datos más complejos, que se parecieran a las situaciones del mundo real y que pudieran ser tratados (más o menos) como una unidad, lo constituyen, entre otros, las "estructuras" del C clásico ("registros" en otros lenguajes). Una estructura es una agregación de datos de diverso tipo construida a criterio del programador mediante la agrupación de elementos ya incluidos en el lenguaje (básicamente los antedichos números y caracteres). Esto supuso un paso en el nivel de abstracción de los datos, aunque las herramientas para manipularlos seguían siendo elementos totalmente diferenciados. En esta etapa ya podía crearse una estructura "cliente" que albergara toda la información antes dispersa, pero aparte de leer y escribir la información en un solo bloque, poco más podía hacerse, los datos tenían que seguir siendo procesados individualmente con expresiones parecidas a: cliente->fecha_ult_compra = date(); tot_factura = suma * cliente->descuento

Upload: vudat

Post on 01-May-2018

219 views

Category:

Documents


3 download

TRANSCRIPT

Page 1:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

11 Introduccioacuten a la POO

sect1 Queacute es eso de los Objetos

En la programacioacuten tradicional existiacutea una clara diferenciacioacuten entre los datos y su manipulacioacuten es decir el conjunto de algoritmos para manejarlos Los tipos de datos eran muy simples todo lo maacutes nuacutemeros de diverso tipo y caracteres (aislados o agrupados en cadenas o matrices) pero nunca elementos heterogeacuteneos

La situacioacuten para el programador era que el lenguaje pareciacutea decirle estos son los posibles contenedores para la informacioacuten que debes manejar (los tipos de datos soportados por el lenguaje) y aquiacute aparte las operaciones que puedes realizar con ellos (las operaciones definidas para dichos datos) Por ejemplo si son datos numeacutericos las operaciones aritmeacuteticas las comparaciones las asignaciones etc Con estas herramientas el programador construiacutea su coacutedigo y para poner un poco de orden en la marantildea de algoritmos solo teniacutea el recurso de agruparlo en funciones

Si se teniacutea que hacer un programa de gestioacuten comercial la informacioacuten correspondiente a un concepto maacutes o menos real por ejemplo un cliente teniacutea que ser desmenuzada en una serie de datos aislados nombre domicilio poblacioacuten provincia teleacutefono condiciones de compra saldo tipo de descuento nuacutemero de vendedor asignado fecha de uacuteltima compra etc etc Luego para hacer una factura todos estos elementos eran tomados y procesados individualmente

Un primer intento de construir tipos de datos maacutes complejos que se parecieran a las situaciones del mundo real y que pudieran ser tratados (maacutes o menos) como una unidad lo constituyen entre otros las estructuras del C claacutesico (registros en otros lenguajes) Una estructura es una agregacioacuten de datos de diverso tipo construida a criterio del programador mediante la agrupacioacuten de elementos ya incluidos en el lenguaje (baacutesicamente los antedichos nuacutemeros y caracteres) Esto supuso un paso en el nivel de abstraccioacuten de los datos aunque las herramientas para manipularlos seguiacutean siendo elementos totalmente diferenciados

En esta etapa ya podiacutea crearse una estructura cliente que albergara toda la informacioacuten antes dispersa pero aparte de leer y escribir la informacioacuten en un solo bloque poco maacutes podiacutea hacerse los datos teniacutean que seguir siendo procesados individualmente con expresiones parecidas a

cliente-gtfecha_ult_compra = date()

tot_factura = suma cliente-gtdescuento

cliente-gtsaldo = cliente-gtsaldo + tot_factura

etc

Ante esta situacioacuten surge una nueva idea crear nuevos tipos de datos agrupando los tipos tradicionales en entidades maacutes complejas que reciben el nombre geneacuterico de clases Las clases son conjuntos de datos definidos por el programador parecidos a las mencionadas estructuras pero con la importante novedad de incluir tambieacuten las herramientas necesarias para su manipulacioacuten es decir operadores y funciones de la programacioacuten tradicional Dicho de otro modo los nuevos tipos de datos pueden ir acompantildeados de su aacutelgebra de las operaciones que se pueden realizar con ellos [3]

La idea es construir una especie de caja negra que incluya no solo los datos tambieacuten los algoritmos necesarios para su manipulacioacuten (sus operaciones) de forma que pueda ser vista desde el exterior (el programador que las usa) como un ente al que se le enviacutean preguntas u oacuterdenes y responde con el resultado [2] Este comportamiento de la clase frente al mundo exterior es lo que se llama su interfaz o protocolo Coacutemo es el detalle de su interior no le interesa al usuario-programador en absoluto solo le interesa conocer la forma de comunicarse con ella y que posibilidades le ofrece El hecho de empaquetar juntos datos y funcionalidad dejando visible al exterior solo lo estrictamente necesario se denomina encapsulamiento y es otro de los distintivos de la POO

Para ilustrar la idea en un caso concreto consideremos un ejemplo claacutesico Supongamos que en un programa tradicional hay que manejar nuacutemeros complejos La solucioacuten es definir dos variables fraccionarias (de coma flotante) R e Y para representar respectivamente las partes reales e imaginaria de cada complejo Luego para obtener por ejemplo la suma (Rr Yr) de dos complejos (R1 Y1) (R2 Y2) tenemos que codificar

Rr = R1 + R2

Yr = Y1 + Y2

para calcular el valor del moacutedulo m tenemos que hacer

m = SQRT( (Rr Rr) + ( Yr Yr) )

asiacute sucesivamente para cualquier manipulacioacuten que queramos efectuar

Supongamos ahora que tenemos esta posibilidad de construir un nuevo tipo de variable que denominaremos la clase de los complejos (la designamos por Cc) y que hemos incluido en dicha clase la informacioacuten necesaria para realizar todas las operaciones permitidas en el aacutelgebra de los nuacutemeros complejos No solo la suma tambieacuten la asignacioacuten la comparacioacuten el caacutelculo del moacutedulo etc Incluso los procedimientos para crear elementos nuevos (complejos) y para destruirlos (eliminarlos de la memoria) Ahora el funcionamiento seriacutea algo parecido a

Cc x = (R1 Y1)

Cc y = (R2 Y2)

Estamos declarando que x e y son objetos de la nueva clase y les estamos asignando los valores correspondientes Fiacutejese que estos objetos son casos concretos del nuevo tipo la clase de los complejos (en el mismo sentido que un 5 es un caso concreto del concepto geneacuterico de nuacutemero entero) En el ejemplo suponemos que R1 Y1 R2 Y2 siguen siendo nuacutemeros fraccionarios tradicionales los mismos que en el ejemplo anterior Fiacutejese tambieacuten que la asignacioacuten x = (R1 Y1) supone que el compilador sabe que al ser x un complejo el siacutembolo = no representa aquiacute la misma operacioacuten que en el caso de por ejemplo z = 6 tambieacuten supone que el compilador sabe que significa exactamente la expresioacuten (R1 Y1) a la derecha

Si ahora queremos calcular el resultado de la suma de los dos complejos y el valor de su moacutedulo solo tenemos que hacer

Cc z = x + y

float m = zmod()

Observe que en la primera liacutenea el operador + no es exactamente el mismo que cuando se utiliza con enteros (por ejemplo en 3 + 5) Esto lo deduce el compilador porque sabe que x e y son complejos (dentro de la nueva clase hemos definido la operacioacuten suma entre sus elementos y le hemos asignado el operador +) Por otra parte en la segunda liacutenea solo tenemos que mandarle al complejo z el mensaje mod() - calcula el moacutedulo - la sintaxis es la sentildealada zmod() Ya sabemos que el resultado es un escalar y lo asignamos al nuacutemero fraccionario m Fiacutejese tambieacuten que en ambas liacuteneas el operador de asignacioacuten = no representa la misma operacioacuten En la primera se trata de una asignacioacuten entre complejos en la segunda es la tradicional asignacioacuten entre nuacutemeros fraccionarios Esta capacidad camaleoacutenica de los operadores es tiacutepica de la POO y se conoce como sobrecarga [4] (veremos que tambieacuten puede haber sobrecarga de funciones) El compilador sabe en cada momento que operador debe utilizar de toda la panoplia disponible aunque esteacuten bajo el mismo siacutembolo lo sabe por el contexto (por la naturaleza de los operandos involucrados)

En la POO es frecuente que meacutetodos anaacutelogos de clases distintas se referencien utilizando las mismas etiquetas Es decir supongamos que tenemos tres clases los Complejos los Vectores y los Racionales Puede ocurrir que por ejemplo el meacutetodo para calcular el moacutedulo se denomine mod() en las tres clases Aunque el resultado sea un nuacutemero racional positivo en los tres casos naturalmente su operatoria es distinta si se aplica a racionales vectores o matrices Sin embargo no existe posibilidad de confusioacuten en el programa porque cuando apliquemos el meacutetodo en cada caso concreto el compilador sabe a cual de ellos nos estamos refiriendo en base a los objetos involucrados Esta caracteriacutestica de la POO da origen a lo que se llama polimorfismo El nombre es bastante descriptivo de su significado y la posibilidad resulta ser de gran utilidad pues simplifica la lectura del coacutedigo Cada vez que encontremos una invocacioacuten al meacutetodo mod tenemos una imagen mental del resultado con independencia del objeto concreto al que se aplique

Llegados a este punto introduciremos alguacuten vocabulario especiacutefico para adaptarnos a la terminologiacutea algo especial que utiliza la POO

En vez de variables como en la programacioacuten claacutesica los datos contenidos en las clases (y en los objetos concretos) se denominan propiedades de forma que en el ejemplo anterior nos referiremos a las partes real R1 e imaginaria Y1 del complejo x como las propiedades R e Y de x (los complejos siguen teniendo una parte real y otra imaginaria incluso en la POO)

Por su parte las operaciones de manipulacioacuten contenidas en las clases (bajo la forma de funciones) reciben el nombre de meacutetodos Siguiendo con el ejemplo anterior en vez de referirnos a funcioacuten mod() que calcula el moacutedulo diremos que mod es un meacutetodo de la clase de los complejos En lenguajes como C++ que puede tener elementos de ambos mundos de la programacioacuten tradicional y de la POO poder utilizar indistintamente los vocablos funcioacuten o meacutetodo es una ventaja ya que nos permite distinguir en cada caso a que nos estamos refiriendo si a funciones tradicionales o a funciones pertenecientes a clases

En uno de los paacuterrafos anteriores hemos dicho estos objetos son casos concretos del nuevo tipo la clase de los complejos utilizando la terminologiacutea correcta diriacuteamos estos objetos son instancias de la clase de los complejos

Como puede verse instancia significa una sustanciacioacuten concreta de un concepto geneacuterico (la clase) En el mismo sentido podriacuteamos decir que el nuacutemero 5 (un objeto) una instancia de la clase de los nuacutemeros enteros que tiene a su vez determinados meacutetodos en este caso las conocidas operaciones aritmeacuteticas suma resta multiplicacioacuten asiacute como las operaciones de asignacioacuten la comparacioacuten etc

Siguiendo este criterio la expresioacuten Cc x = (R1 Y1) no se dice declaracioacuten de x como objeto de la nueva clase Es maacutes correcto sentildealar x es una instancia de la clase de los complejos Al hecho de sustanciar un objeto concreto de una clase se le denomina instanciar dicho objeto Esta operacioacuten (crear un objeto) estaacute encomendada a un tipo especial de meacutetodos denominados constructores Siguiendo con nuestro ejemplo podemos suponer que la expresioacuten

Cc c1(1 3)

crea un complejo c1 cuyas partes real e imaginaria valen respectivamente 1 y 3 y que este objeto ha sido creado por una funcioacuten (meacutetodo) de Cc cuya misioacuten es precisamente crear objetos seguacuten ciertos paraacutemetros que son pasados como argumentos de la funcioacuten

En ocasiones cuando se quiere distinguir entre los valores y funcionalidades geneacutericos (de las clases) y los concretos (de los objetos) se suelen emplear las expresiones propiedades de clase y meacutetodos de clase para las primeras y propiedades de instancia y meacutetodos de instancia para los segundos Asiacute mismo cuando se quiere distinguir entre una funcioacuten normal (de la programacioacuten tradicional) y una funcioacuten perteneciente a una clase (un meacutetodo de la clase) se suele emplear para esta uacuteltima la expresioacuten funcioacuten miembro (se sobreentiende funcioacuten miembro_de_una_clase) [1]

Como puede suponerse el encapsulamiento junto con la capacidad de sobrecarga constituyen en si mismos una posibilidad de abstraccioacuten para los datos mayor que la que facilitaba la programacioacuten tradicional Ya siacute puede pensarse en un complejo como algo que tiene existencia real dentro de nuestro coacutedigo ya que lo tratamos (manipulamos) como ente independiente con caracteriacutesticas propias de forma parecida a la imagen que de eacutel tenemos en nuestra mente

Con ser lo anterior un paso importante sin embargo las mejoras de la POO respecto de la programacioacuten claacutesica no terminan aquiacute Los Lenguajes Orientados a Objeto como el C++ ademaacutes de los tipos de datos tradicionales incluyen algunas clases pre-construidas pero debido al hecho de que la construccioacuten de un nuevo tipo de variable (como la clase Cc de los complejos en el ejemplo anterior) requiere un cierto trabajo de programacioacuten inicial para disentildear la clase se pensoacute que seriacutea estupendo poder aprovechar el trabajo realizado en determinados disentildeos para a partir de ellos obtener otros nuevos de caracteriacutesticas maacutes o menos parecidas Se trataba en suma de intentar reutilizar el coacutedigo dentro de lo posible en el mismo sentido que lo hacemos cuando tenemos que escribir una carta circular y buscamos en el ordenador si hay alguna anterior parecida para utilizarla junto con el procesador de textos como punto de comienzo para la nueva Para esto se dotoacute al lenguaje de dos nuevas capacidades la Herencia y la Composicioacuten

Por herencia (Inheritance) se entiende la capacidad de poder crear nuevas clases a partir de alguna anterior de forma que las nuevas heredan las caracteriacutesticas de sus ancestros (propiedades y meacutetodos) Se trata por tanto de la capacidad de crear nuevos tipos de datos a partir de los anteriores Una caracteriacutestica especial de la herencia es que si se cambia el comportamiento de la clase antecesora (tambieacuten llamada padre base o super) tambieacuten cambiaraacute el comportamiento de las clases derivadas de ella (descendientes)

Como puede deducirse faacutecilmente la herencia establece lo que se llama una jerarquiacutea de clases del mismo aspecto que el aacuterbol genealoacutegico de una familia Se entiende tambieacuten que estos conceptos representan niveles de abstraccioacuten que permiten acercar la programacioacuten a la realidad del mundo fiacutesico tal como lo concebimos Por ejemplo entendemos que un motor eleacutectrico deriva de la clase general de los motores de la cual derivan tambieacuten los de gasolina diesel vapor etc y que sin dejar de ser motores cada subclase tiene sus caracteriacutesticas peculiares

Por supuesto que no tendriacutea ninguacuten sentido utilizar la herencia para crear simplemente un cloacutenico de la clase base En realidad como en el ejemplo de la carta circular la herencia se emplea como un primer paso (partir de algo existente) para a continuacioacuten perfilar los comportamientos o datos que queremos pulir en la nueva versioacuten de la clase Como lo que principalmente interesa al usuario de una clase es su interfaz son justamente algunos aspectos de esta interfaz los que se modifican al objeto de adecuar la nueva subclase a las necesidades especiacuteficas del caso Por lo general esta modificacioacuten de la interfaz se consigue de dos formas

1 Antildeadiendo propiedades yo meacutetodos que no existiacutean en la clase base 2 Sobrescribiendo propiedades del mismo nombre con distintos comportamientos (sobrecarga yo

polimorfismo)

Aunque la herencia es uno de los pilares de la POO tiene tambieacuten sus inconvenientes Por ejemplo dado que el compilador debe imponer ciertas caracteriacutesticas en tiempo de compilacioacuten sobre las clases creadas por herencia esto resulta en cierta rigidez posterior Sin embargo como hemos visto una de sus ventajas es la reutilizacioacuten del coacutedigo

La composicioacuten (tambieacuten llamada herencia muacuteltiple) es la segunda viacutea para crear nuevas clases a partir de las existentes Por composicioacuten se entiende la capacidad que presenta la POO de ensamblar un nuevo tipo (clase) cuyos elementos o piezas son otras clases Es posible declarar clases derivadas de las existentes especificando que heredan los miembros de una o maacutes clases antecesoras Siguiendo con el siacutemil de la carta circular la composicioacuten equivaldriacutea a escribirla reutilizando trozos de cartas anteriores Es claacutesico el ejemplo de sentildealar que podriacuteamos crear una clase coche declarando que tiene un motor y cuatro ruedas

bastidor aire acondicionado etc elementos estos pertenecientes a la clase de los motores de las ruedas los bastidores y los sistemas de climatizacioacuten respectivamente Este sistema tiene tambieacuten sus ventajas e inconvenientes pero es muy flexible ya que incluso pueden cambiarse los componentes en tiempo de ejecucioacuten

sect2 Resumen

Como resumen de este raacutepido repaso podemos sentildealar que la Programacioacuten Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas entre las que destaca la reutilizacioacuten del coacutedigo A los acadeacutemicos les gusta decir que se sustenta en cuatro columnas a las que ya hemos hecho referencia

Encapsulamiento Poder separar la interfaz de una clase de su implementacioacuten o dicho en otras palabras no es necesario conocer los detalles de coacutemo estaacuten implementadas las propiedades para poder utilizarlas Los objetos funcionan a modo de caja negra en la que estaacuten empaquetados los datos y las instrucciones para su manipulacioacuten de las que conocemos solo lo necesario para utilizarla

Herencia Crear nuevos elementos a partir de los existentes de forma que heredan las propiedades de sus ancestros Existen dos clases de herencia simple y muacuteltiple

Sobrecarga Posibilidad de crear diferentes meacutetodos dentro de una clase que comparten el mismo nombre pero que aceptan argumentos diferentes y se comporten de forma distinta seguacuten la naturaleza de estos argumentos ( 441a)

Polimorfismo Es una caracteriacutestica que resulta de gran ayuda en programacioacuten pues facilita la claridad y consistencia del coacutedigo aunque es un concepto bastante geneacuterico (y frecuentemente malinterpretado) Se conoce con este nombre el hecho de que un meacutetodo tiene el mismo nombre y resulta en el mismo efecto baacutesico pero estaacute implementado de forma distinta en las distintas clases de una jerarquiacutea

12 El lenguaje C++

Learn not just the hows but the whys too Greg Comeau [7]

sect1 Generalidades

C++ es un lenguaje imperativo orientado a objetos derivado del C [1] En realidad un superconjunto de C que nacioacute para antildeadirle cualidades y caracteriacutesticas de las que careciacutea El resultado es que como su ancestro sigue muy ligado al hardware subyacente manteniendo una considerable potencia para programacioacuten a bajo nivel pero se la han antildeadido elementos que le permiten tambieacuten un estilo de programacioacuten con alto nivel de abstraccioacuten

Nota estrictamente hablando C no es un subconjunto de C++ de hecho es posible escribir coacutedigo C que es ilegal en C++ Pero a efectos praacutecticos dado el esfuerzo de compatibilidad desplegado en su disentildeo puede considerarse que C++ es una extensioacuten del C claacutesico La definicioacuten oficial del lenguaje nos dice que C++ es un lenguaje de propoacutesito general basado en el C al que se han antildeadido nuevos tipos de datos clases plantillas mecanismo de excepciones sistema de espacios de nombres funciones inline sobrecarga de operadores referencias operadores para manejo de memoria persistente y algunas utilidades adicionales de libreriacutea (en realidad la libreriacutea Estaacutendar C es un subconjunto de la libreriacutea C++)

Respecto a su antecesor se ha procurando mantener una exquisita compatibilidad hacia atraacutes por dos razones [2] poder reutilizar la enorme cantidad de coacutedigo C existente y facilitar una transicioacuten lo maacutes fluida posible a los programadores de C claacutesico de forma que pudieran pasar sus programas a C++ e ir modificaacutendolos (hacieacutendolos maacutes ++) de forma gradual De hecho los primeros compiladores C++ lo que

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 2:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Para ilustrar la idea en un caso concreto consideremos un ejemplo claacutesico Supongamos que en un programa tradicional hay que manejar nuacutemeros complejos La solucioacuten es definir dos variables fraccionarias (de coma flotante) R e Y para representar respectivamente las partes reales e imaginaria de cada complejo Luego para obtener por ejemplo la suma (Rr Yr) de dos complejos (R1 Y1) (R2 Y2) tenemos que codificar

Rr = R1 + R2

Yr = Y1 + Y2

para calcular el valor del moacutedulo m tenemos que hacer

m = SQRT( (Rr Rr) + ( Yr Yr) )

asiacute sucesivamente para cualquier manipulacioacuten que queramos efectuar

Supongamos ahora que tenemos esta posibilidad de construir un nuevo tipo de variable que denominaremos la clase de los complejos (la designamos por Cc) y que hemos incluido en dicha clase la informacioacuten necesaria para realizar todas las operaciones permitidas en el aacutelgebra de los nuacutemeros complejos No solo la suma tambieacuten la asignacioacuten la comparacioacuten el caacutelculo del moacutedulo etc Incluso los procedimientos para crear elementos nuevos (complejos) y para destruirlos (eliminarlos de la memoria) Ahora el funcionamiento seriacutea algo parecido a

Cc x = (R1 Y1)

Cc y = (R2 Y2)

Estamos declarando que x e y son objetos de la nueva clase y les estamos asignando los valores correspondientes Fiacutejese que estos objetos son casos concretos del nuevo tipo la clase de los complejos (en el mismo sentido que un 5 es un caso concreto del concepto geneacuterico de nuacutemero entero) En el ejemplo suponemos que R1 Y1 R2 Y2 siguen siendo nuacutemeros fraccionarios tradicionales los mismos que en el ejemplo anterior Fiacutejese tambieacuten que la asignacioacuten x = (R1 Y1) supone que el compilador sabe que al ser x un complejo el siacutembolo = no representa aquiacute la misma operacioacuten que en el caso de por ejemplo z = 6 tambieacuten supone que el compilador sabe que significa exactamente la expresioacuten (R1 Y1) a la derecha

Si ahora queremos calcular el resultado de la suma de los dos complejos y el valor de su moacutedulo solo tenemos que hacer

Cc z = x + y

float m = zmod()

Observe que en la primera liacutenea el operador + no es exactamente el mismo que cuando se utiliza con enteros (por ejemplo en 3 + 5) Esto lo deduce el compilador porque sabe que x e y son complejos (dentro de la nueva clase hemos definido la operacioacuten suma entre sus elementos y le hemos asignado el operador +) Por otra parte en la segunda liacutenea solo tenemos que mandarle al complejo z el mensaje mod() - calcula el moacutedulo - la sintaxis es la sentildealada zmod() Ya sabemos que el resultado es un escalar y lo asignamos al nuacutemero fraccionario m Fiacutejese tambieacuten que en ambas liacuteneas el operador de asignacioacuten = no representa la misma operacioacuten En la primera se trata de una asignacioacuten entre complejos en la segunda es la tradicional asignacioacuten entre nuacutemeros fraccionarios Esta capacidad camaleoacutenica de los operadores es tiacutepica de la POO y se conoce como sobrecarga [4] (veremos que tambieacuten puede haber sobrecarga de funciones) El compilador sabe en cada momento que operador debe utilizar de toda la panoplia disponible aunque esteacuten bajo el mismo siacutembolo lo sabe por el contexto (por la naturaleza de los operandos involucrados)

En la POO es frecuente que meacutetodos anaacutelogos de clases distintas se referencien utilizando las mismas etiquetas Es decir supongamos que tenemos tres clases los Complejos los Vectores y los Racionales Puede ocurrir que por ejemplo el meacutetodo para calcular el moacutedulo se denomine mod() en las tres clases Aunque el resultado sea un nuacutemero racional positivo en los tres casos naturalmente su operatoria es distinta si se aplica a racionales vectores o matrices Sin embargo no existe posibilidad de confusioacuten en el programa porque cuando apliquemos el meacutetodo en cada caso concreto el compilador sabe a cual de ellos nos estamos refiriendo en base a los objetos involucrados Esta caracteriacutestica de la POO da origen a lo que se llama polimorfismo El nombre es bastante descriptivo de su significado y la posibilidad resulta ser de gran utilidad pues simplifica la lectura del coacutedigo Cada vez que encontremos una invocacioacuten al meacutetodo mod tenemos una imagen mental del resultado con independencia del objeto concreto al que se aplique

Llegados a este punto introduciremos alguacuten vocabulario especiacutefico para adaptarnos a la terminologiacutea algo especial que utiliza la POO

En vez de variables como en la programacioacuten claacutesica los datos contenidos en las clases (y en los objetos concretos) se denominan propiedades de forma que en el ejemplo anterior nos referiremos a las partes real R1 e imaginaria Y1 del complejo x como las propiedades R e Y de x (los complejos siguen teniendo una parte real y otra imaginaria incluso en la POO)

Por su parte las operaciones de manipulacioacuten contenidas en las clases (bajo la forma de funciones) reciben el nombre de meacutetodos Siguiendo con el ejemplo anterior en vez de referirnos a funcioacuten mod() que calcula el moacutedulo diremos que mod es un meacutetodo de la clase de los complejos En lenguajes como C++ que puede tener elementos de ambos mundos de la programacioacuten tradicional y de la POO poder utilizar indistintamente los vocablos funcioacuten o meacutetodo es una ventaja ya que nos permite distinguir en cada caso a que nos estamos refiriendo si a funciones tradicionales o a funciones pertenecientes a clases

En uno de los paacuterrafos anteriores hemos dicho estos objetos son casos concretos del nuevo tipo la clase de los complejos utilizando la terminologiacutea correcta diriacuteamos estos objetos son instancias de la clase de los complejos

Como puede verse instancia significa una sustanciacioacuten concreta de un concepto geneacuterico (la clase) En el mismo sentido podriacuteamos decir que el nuacutemero 5 (un objeto) una instancia de la clase de los nuacutemeros enteros que tiene a su vez determinados meacutetodos en este caso las conocidas operaciones aritmeacuteticas suma resta multiplicacioacuten asiacute como las operaciones de asignacioacuten la comparacioacuten etc

Siguiendo este criterio la expresioacuten Cc x = (R1 Y1) no se dice declaracioacuten de x como objeto de la nueva clase Es maacutes correcto sentildealar x es una instancia de la clase de los complejos Al hecho de sustanciar un objeto concreto de una clase se le denomina instanciar dicho objeto Esta operacioacuten (crear un objeto) estaacute encomendada a un tipo especial de meacutetodos denominados constructores Siguiendo con nuestro ejemplo podemos suponer que la expresioacuten

Cc c1(1 3)

crea un complejo c1 cuyas partes real e imaginaria valen respectivamente 1 y 3 y que este objeto ha sido creado por una funcioacuten (meacutetodo) de Cc cuya misioacuten es precisamente crear objetos seguacuten ciertos paraacutemetros que son pasados como argumentos de la funcioacuten

En ocasiones cuando se quiere distinguir entre los valores y funcionalidades geneacutericos (de las clases) y los concretos (de los objetos) se suelen emplear las expresiones propiedades de clase y meacutetodos de clase para las primeras y propiedades de instancia y meacutetodos de instancia para los segundos Asiacute mismo cuando se quiere distinguir entre una funcioacuten normal (de la programacioacuten tradicional) y una funcioacuten perteneciente a una clase (un meacutetodo de la clase) se suele emplear para esta uacuteltima la expresioacuten funcioacuten miembro (se sobreentiende funcioacuten miembro_de_una_clase) [1]

Como puede suponerse el encapsulamiento junto con la capacidad de sobrecarga constituyen en si mismos una posibilidad de abstraccioacuten para los datos mayor que la que facilitaba la programacioacuten tradicional Ya siacute puede pensarse en un complejo como algo que tiene existencia real dentro de nuestro coacutedigo ya que lo tratamos (manipulamos) como ente independiente con caracteriacutesticas propias de forma parecida a la imagen que de eacutel tenemos en nuestra mente

Con ser lo anterior un paso importante sin embargo las mejoras de la POO respecto de la programacioacuten claacutesica no terminan aquiacute Los Lenguajes Orientados a Objeto como el C++ ademaacutes de los tipos de datos tradicionales incluyen algunas clases pre-construidas pero debido al hecho de que la construccioacuten de un nuevo tipo de variable (como la clase Cc de los complejos en el ejemplo anterior) requiere un cierto trabajo de programacioacuten inicial para disentildear la clase se pensoacute que seriacutea estupendo poder aprovechar el trabajo realizado en determinados disentildeos para a partir de ellos obtener otros nuevos de caracteriacutesticas maacutes o menos parecidas Se trataba en suma de intentar reutilizar el coacutedigo dentro de lo posible en el mismo sentido que lo hacemos cuando tenemos que escribir una carta circular y buscamos en el ordenador si hay alguna anterior parecida para utilizarla junto con el procesador de textos como punto de comienzo para la nueva Para esto se dotoacute al lenguaje de dos nuevas capacidades la Herencia y la Composicioacuten

Por herencia (Inheritance) se entiende la capacidad de poder crear nuevas clases a partir de alguna anterior de forma que las nuevas heredan las caracteriacutesticas de sus ancestros (propiedades y meacutetodos) Se trata por tanto de la capacidad de crear nuevos tipos de datos a partir de los anteriores Una caracteriacutestica especial de la herencia es que si se cambia el comportamiento de la clase antecesora (tambieacuten llamada padre base o super) tambieacuten cambiaraacute el comportamiento de las clases derivadas de ella (descendientes)

Como puede deducirse faacutecilmente la herencia establece lo que se llama una jerarquiacutea de clases del mismo aspecto que el aacuterbol genealoacutegico de una familia Se entiende tambieacuten que estos conceptos representan niveles de abstraccioacuten que permiten acercar la programacioacuten a la realidad del mundo fiacutesico tal como lo concebimos Por ejemplo entendemos que un motor eleacutectrico deriva de la clase general de los motores de la cual derivan tambieacuten los de gasolina diesel vapor etc y que sin dejar de ser motores cada subclase tiene sus caracteriacutesticas peculiares

Por supuesto que no tendriacutea ninguacuten sentido utilizar la herencia para crear simplemente un cloacutenico de la clase base En realidad como en el ejemplo de la carta circular la herencia se emplea como un primer paso (partir de algo existente) para a continuacioacuten perfilar los comportamientos o datos que queremos pulir en la nueva versioacuten de la clase Como lo que principalmente interesa al usuario de una clase es su interfaz son justamente algunos aspectos de esta interfaz los que se modifican al objeto de adecuar la nueva subclase a las necesidades especiacuteficas del caso Por lo general esta modificacioacuten de la interfaz se consigue de dos formas

1 Antildeadiendo propiedades yo meacutetodos que no existiacutean en la clase base 2 Sobrescribiendo propiedades del mismo nombre con distintos comportamientos (sobrecarga yo

polimorfismo)

Aunque la herencia es uno de los pilares de la POO tiene tambieacuten sus inconvenientes Por ejemplo dado que el compilador debe imponer ciertas caracteriacutesticas en tiempo de compilacioacuten sobre las clases creadas por herencia esto resulta en cierta rigidez posterior Sin embargo como hemos visto una de sus ventajas es la reutilizacioacuten del coacutedigo

La composicioacuten (tambieacuten llamada herencia muacuteltiple) es la segunda viacutea para crear nuevas clases a partir de las existentes Por composicioacuten se entiende la capacidad que presenta la POO de ensamblar un nuevo tipo (clase) cuyos elementos o piezas son otras clases Es posible declarar clases derivadas de las existentes especificando que heredan los miembros de una o maacutes clases antecesoras Siguiendo con el siacutemil de la carta circular la composicioacuten equivaldriacutea a escribirla reutilizando trozos de cartas anteriores Es claacutesico el ejemplo de sentildealar que podriacuteamos crear una clase coche declarando que tiene un motor y cuatro ruedas

bastidor aire acondicionado etc elementos estos pertenecientes a la clase de los motores de las ruedas los bastidores y los sistemas de climatizacioacuten respectivamente Este sistema tiene tambieacuten sus ventajas e inconvenientes pero es muy flexible ya que incluso pueden cambiarse los componentes en tiempo de ejecucioacuten

sect2 Resumen

Como resumen de este raacutepido repaso podemos sentildealar que la Programacioacuten Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas entre las que destaca la reutilizacioacuten del coacutedigo A los acadeacutemicos les gusta decir que se sustenta en cuatro columnas a las que ya hemos hecho referencia

Encapsulamiento Poder separar la interfaz de una clase de su implementacioacuten o dicho en otras palabras no es necesario conocer los detalles de coacutemo estaacuten implementadas las propiedades para poder utilizarlas Los objetos funcionan a modo de caja negra en la que estaacuten empaquetados los datos y las instrucciones para su manipulacioacuten de las que conocemos solo lo necesario para utilizarla

Herencia Crear nuevos elementos a partir de los existentes de forma que heredan las propiedades de sus ancestros Existen dos clases de herencia simple y muacuteltiple

Sobrecarga Posibilidad de crear diferentes meacutetodos dentro de una clase que comparten el mismo nombre pero que aceptan argumentos diferentes y se comporten de forma distinta seguacuten la naturaleza de estos argumentos ( 441a)

Polimorfismo Es una caracteriacutestica que resulta de gran ayuda en programacioacuten pues facilita la claridad y consistencia del coacutedigo aunque es un concepto bastante geneacuterico (y frecuentemente malinterpretado) Se conoce con este nombre el hecho de que un meacutetodo tiene el mismo nombre y resulta en el mismo efecto baacutesico pero estaacute implementado de forma distinta en las distintas clases de una jerarquiacutea

12 El lenguaje C++

Learn not just the hows but the whys too Greg Comeau [7]

sect1 Generalidades

C++ es un lenguaje imperativo orientado a objetos derivado del C [1] En realidad un superconjunto de C que nacioacute para antildeadirle cualidades y caracteriacutesticas de las que careciacutea El resultado es que como su ancestro sigue muy ligado al hardware subyacente manteniendo una considerable potencia para programacioacuten a bajo nivel pero se la han antildeadido elementos que le permiten tambieacuten un estilo de programacioacuten con alto nivel de abstraccioacuten

Nota estrictamente hablando C no es un subconjunto de C++ de hecho es posible escribir coacutedigo C que es ilegal en C++ Pero a efectos praacutecticos dado el esfuerzo de compatibilidad desplegado en su disentildeo puede considerarse que C++ es una extensioacuten del C claacutesico La definicioacuten oficial del lenguaje nos dice que C++ es un lenguaje de propoacutesito general basado en el C al que se han antildeadido nuevos tipos de datos clases plantillas mecanismo de excepciones sistema de espacios de nombres funciones inline sobrecarga de operadores referencias operadores para manejo de memoria persistente y algunas utilidades adicionales de libreriacutea (en realidad la libreriacutea Estaacutendar C es un subconjunto de la libreriacutea C++)

Respecto a su antecesor se ha procurando mantener una exquisita compatibilidad hacia atraacutes por dos razones [2] poder reutilizar la enorme cantidad de coacutedigo C existente y facilitar una transicioacuten lo maacutes fluida posible a los programadores de C claacutesico de forma que pudieran pasar sus programas a C++ e ir modificaacutendolos (hacieacutendolos maacutes ++) de forma gradual De hecho los primeros compiladores C++ lo que

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 3:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

En la POO es frecuente que meacutetodos anaacutelogos de clases distintas se referencien utilizando las mismas etiquetas Es decir supongamos que tenemos tres clases los Complejos los Vectores y los Racionales Puede ocurrir que por ejemplo el meacutetodo para calcular el moacutedulo se denomine mod() en las tres clases Aunque el resultado sea un nuacutemero racional positivo en los tres casos naturalmente su operatoria es distinta si se aplica a racionales vectores o matrices Sin embargo no existe posibilidad de confusioacuten en el programa porque cuando apliquemos el meacutetodo en cada caso concreto el compilador sabe a cual de ellos nos estamos refiriendo en base a los objetos involucrados Esta caracteriacutestica de la POO da origen a lo que se llama polimorfismo El nombre es bastante descriptivo de su significado y la posibilidad resulta ser de gran utilidad pues simplifica la lectura del coacutedigo Cada vez que encontremos una invocacioacuten al meacutetodo mod tenemos una imagen mental del resultado con independencia del objeto concreto al que se aplique

Llegados a este punto introduciremos alguacuten vocabulario especiacutefico para adaptarnos a la terminologiacutea algo especial que utiliza la POO

En vez de variables como en la programacioacuten claacutesica los datos contenidos en las clases (y en los objetos concretos) se denominan propiedades de forma que en el ejemplo anterior nos referiremos a las partes real R1 e imaginaria Y1 del complejo x como las propiedades R e Y de x (los complejos siguen teniendo una parte real y otra imaginaria incluso en la POO)

Por su parte las operaciones de manipulacioacuten contenidas en las clases (bajo la forma de funciones) reciben el nombre de meacutetodos Siguiendo con el ejemplo anterior en vez de referirnos a funcioacuten mod() que calcula el moacutedulo diremos que mod es un meacutetodo de la clase de los complejos En lenguajes como C++ que puede tener elementos de ambos mundos de la programacioacuten tradicional y de la POO poder utilizar indistintamente los vocablos funcioacuten o meacutetodo es una ventaja ya que nos permite distinguir en cada caso a que nos estamos refiriendo si a funciones tradicionales o a funciones pertenecientes a clases

En uno de los paacuterrafos anteriores hemos dicho estos objetos son casos concretos del nuevo tipo la clase de los complejos utilizando la terminologiacutea correcta diriacuteamos estos objetos son instancias de la clase de los complejos

Como puede verse instancia significa una sustanciacioacuten concreta de un concepto geneacuterico (la clase) En el mismo sentido podriacuteamos decir que el nuacutemero 5 (un objeto) una instancia de la clase de los nuacutemeros enteros que tiene a su vez determinados meacutetodos en este caso las conocidas operaciones aritmeacuteticas suma resta multiplicacioacuten asiacute como las operaciones de asignacioacuten la comparacioacuten etc

Siguiendo este criterio la expresioacuten Cc x = (R1 Y1) no se dice declaracioacuten de x como objeto de la nueva clase Es maacutes correcto sentildealar x es una instancia de la clase de los complejos Al hecho de sustanciar un objeto concreto de una clase se le denomina instanciar dicho objeto Esta operacioacuten (crear un objeto) estaacute encomendada a un tipo especial de meacutetodos denominados constructores Siguiendo con nuestro ejemplo podemos suponer que la expresioacuten

Cc c1(1 3)

crea un complejo c1 cuyas partes real e imaginaria valen respectivamente 1 y 3 y que este objeto ha sido creado por una funcioacuten (meacutetodo) de Cc cuya misioacuten es precisamente crear objetos seguacuten ciertos paraacutemetros que son pasados como argumentos de la funcioacuten

En ocasiones cuando se quiere distinguir entre los valores y funcionalidades geneacutericos (de las clases) y los concretos (de los objetos) se suelen emplear las expresiones propiedades de clase y meacutetodos de clase para las primeras y propiedades de instancia y meacutetodos de instancia para los segundos Asiacute mismo cuando se quiere distinguir entre una funcioacuten normal (de la programacioacuten tradicional) y una funcioacuten perteneciente a una clase (un meacutetodo de la clase) se suele emplear para esta uacuteltima la expresioacuten funcioacuten miembro (se sobreentiende funcioacuten miembro_de_una_clase) [1]

Como puede suponerse el encapsulamiento junto con la capacidad de sobrecarga constituyen en si mismos una posibilidad de abstraccioacuten para los datos mayor que la que facilitaba la programacioacuten tradicional Ya siacute puede pensarse en un complejo como algo que tiene existencia real dentro de nuestro coacutedigo ya que lo tratamos (manipulamos) como ente independiente con caracteriacutesticas propias de forma parecida a la imagen que de eacutel tenemos en nuestra mente

Con ser lo anterior un paso importante sin embargo las mejoras de la POO respecto de la programacioacuten claacutesica no terminan aquiacute Los Lenguajes Orientados a Objeto como el C++ ademaacutes de los tipos de datos tradicionales incluyen algunas clases pre-construidas pero debido al hecho de que la construccioacuten de un nuevo tipo de variable (como la clase Cc de los complejos en el ejemplo anterior) requiere un cierto trabajo de programacioacuten inicial para disentildear la clase se pensoacute que seriacutea estupendo poder aprovechar el trabajo realizado en determinados disentildeos para a partir de ellos obtener otros nuevos de caracteriacutesticas maacutes o menos parecidas Se trataba en suma de intentar reutilizar el coacutedigo dentro de lo posible en el mismo sentido que lo hacemos cuando tenemos que escribir una carta circular y buscamos en el ordenador si hay alguna anterior parecida para utilizarla junto con el procesador de textos como punto de comienzo para la nueva Para esto se dotoacute al lenguaje de dos nuevas capacidades la Herencia y la Composicioacuten

Por herencia (Inheritance) se entiende la capacidad de poder crear nuevas clases a partir de alguna anterior de forma que las nuevas heredan las caracteriacutesticas de sus ancestros (propiedades y meacutetodos) Se trata por tanto de la capacidad de crear nuevos tipos de datos a partir de los anteriores Una caracteriacutestica especial de la herencia es que si se cambia el comportamiento de la clase antecesora (tambieacuten llamada padre base o super) tambieacuten cambiaraacute el comportamiento de las clases derivadas de ella (descendientes)

Como puede deducirse faacutecilmente la herencia establece lo que se llama una jerarquiacutea de clases del mismo aspecto que el aacuterbol genealoacutegico de una familia Se entiende tambieacuten que estos conceptos representan niveles de abstraccioacuten que permiten acercar la programacioacuten a la realidad del mundo fiacutesico tal como lo concebimos Por ejemplo entendemos que un motor eleacutectrico deriva de la clase general de los motores de la cual derivan tambieacuten los de gasolina diesel vapor etc y que sin dejar de ser motores cada subclase tiene sus caracteriacutesticas peculiares

Por supuesto que no tendriacutea ninguacuten sentido utilizar la herencia para crear simplemente un cloacutenico de la clase base En realidad como en el ejemplo de la carta circular la herencia se emplea como un primer paso (partir de algo existente) para a continuacioacuten perfilar los comportamientos o datos que queremos pulir en la nueva versioacuten de la clase Como lo que principalmente interesa al usuario de una clase es su interfaz son justamente algunos aspectos de esta interfaz los que se modifican al objeto de adecuar la nueva subclase a las necesidades especiacuteficas del caso Por lo general esta modificacioacuten de la interfaz se consigue de dos formas

1 Antildeadiendo propiedades yo meacutetodos que no existiacutean en la clase base 2 Sobrescribiendo propiedades del mismo nombre con distintos comportamientos (sobrecarga yo

polimorfismo)

Aunque la herencia es uno de los pilares de la POO tiene tambieacuten sus inconvenientes Por ejemplo dado que el compilador debe imponer ciertas caracteriacutesticas en tiempo de compilacioacuten sobre las clases creadas por herencia esto resulta en cierta rigidez posterior Sin embargo como hemos visto una de sus ventajas es la reutilizacioacuten del coacutedigo

La composicioacuten (tambieacuten llamada herencia muacuteltiple) es la segunda viacutea para crear nuevas clases a partir de las existentes Por composicioacuten se entiende la capacidad que presenta la POO de ensamblar un nuevo tipo (clase) cuyos elementos o piezas son otras clases Es posible declarar clases derivadas de las existentes especificando que heredan los miembros de una o maacutes clases antecesoras Siguiendo con el siacutemil de la carta circular la composicioacuten equivaldriacutea a escribirla reutilizando trozos de cartas anteriores Es claacutesico el ejemplo de sentildealar que podriacuteamos crear una clase coche declarando que tiene un motor y cuatro ruedas

bastidor aire acondicionado etc elementos estos pertenecientes a la clase de los motores de las ruedas los bastidores y los sistemas de climatizacioacuten respectivamente Este sistema tiene tambieacuten sus ventajas e inconvenientes pero es muy flexible ya que incluso pueden cambiarse los componentes en tiempo de ejecucioacuten

sect2 Resumen

Como resumen de este raacutepido repaso podemos sentildealar que la Programacioacuten Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas entre las que destaca la reutilizacioacuten del coacutedigo A los acadeacutemicos les gusta decir que se sustenta en cuatro columnas a las que ya hemos hecho referencia

Encapsulamiento Poder separar la interfaz de una clase de su implementacioacuten o dicho en otras palabras no es necesario conocer los detalles de coacutemo estaacuten implementadas las propiedades para poder utilizarlas Los objetos funcionan a modo de caja negra en la que estaacuten empaquetados los datos y las instrucciones para su manipulacioacuten de las que conocemos solo lo necesario para utilizarla

Herencia Crear nuevos elementos a partir de los existentes de forma que heredan las propiedades de sus ancestros Existen dos clases de herencia simple y muacuteltiple

Sobrecarga Posibilidad de crear diferentes meacutetodos dentro de una clase que comparten el mismo nombre pero que aceptan argumentos diferentes y se comporten de forma distinta seguacuten la naturaleza de estos argumentos ( 441a)

Polimorfismo Es una caracteriacutestica que resulta de gran ayuda en programacioacuten pues facilita la claridad y consistencia del coacutedigo aunque es un concepto bastante geneacuterico (y frecuentemente malinterpretado) Se conoce con este nombre el hecho de que un meacutetodo tiene el mismo nombre y resulta en el mismo efecto baacutesico pero estaacute implementado de forma distinta en las distintas clases de una jerarquiacutea

12 El lenguaje C++

Learn not just the hows but the whys too Greg Comeau [7]

sect1 Generalidades

C++ es un lenguaje imperativo orientado a objetos derivado del C [1] En realidad un superconjunto de C que nacioacute para antildeadirle cualidades y caracteriacutesticas de las que careciacutea El resultado es que como su ancestro sigue muy ligado al hardware subyacente manteniendo una considerable potencia para programacioacuten a bajo nivel pero se la han antildeadido elementos que le permiten tambieacuten un estilo de programacioacuten con alto nivel de abstraccioacuten

Nota estrictamente hablando C no es un subconjunto de C++ de hecho es posible escribir coacutedigo C que es ilegal en C++ Pero a efectos praacutecticos dado el esfuerzo de compatibilidad desplegado en su disentildeo puede considerarse que C++ es una extensioacuten del C claacutesico La definicioacuten oficial del lenguaje nos dice que C++ es un lenguaje de propoacutesito general basado en el C al que se han antildeadido nuevos tipos de datos clases plantillas mecanismo de excepciones sistema de espacios de nombres funciones inline sobrecarga de operadores referencias operadores para manejo de memoria persistente y algunas utilidades adicionales de libreriacutea (en realidad la libreriacutea Estaacutendar C es un subconjunto de la libreriacutea C++)

Respecto a su antecesor se ha procurando mantener una exquisita compatibilidad hacia atraacutes por dos razones [2] poder reutilizar la enorme cantidad de coacutedigo C existente y facilitar una transicioacuten lo maacutes fluida posible a los programadores de C claacutesico de forma que pudieran pasar sus programas a C++ e ir modificaacutendolos (hacieacutendolos maacutes ++) de forma gradual De hecho los primeros compiladores C++ lo que

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 4:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Como puede suponerse el encapsulamiento junto con la capacidad de sobrecarga constituyen en si mismos una posibilidad de abstraccioacuten para los datos mayor que la que facilitaba la programacioacuten tradicional Ya siacute puede pensarse en un complejo como algo que tiene existencia real dentro de nuestro coacutedigo ya que lo tratamos (manipulamos) como ente independiente con caracteriacutesticas propias de forma parecida a la imagen que de eacutel tenemos en nuestra mente

Con ser lo anterior un paso importante sin embargo las mejoras de la POO respecto de la programacioacuten claacutesica no terminan aquiacute Los Lenguajes Orientados a Objeto como el C++ ademaacutes de los tipos de datos tradicionales incluyen algunas clases pre-construidas pero debido al hecho de que la construccioacuten de un nuevo tipo de variable (como la clase Cc de los complejos en el ejemplo anterior) requiere un cierto trabajo de programacioacuten inicial para disentildear la clase se pensoacute que seriacutea estupendo poder aprovechar el trabajo realizado en determinados disentildeos para a partir de ellos obtener otros nuevos de caracteriacutesticas maacutes o menos parecidas Se trataba en suma de intentar reutilizar el coacutedigo dentro de lo posible en el mismo sentido que lo hacemos cuando tenemos que escribir una carta circular y buscamos en el ordenador si hay alguna anterior parecida para utilizarla junto con el procesador de textos como punto de comienzo para la nueva Para esto se dotoacute al lenguaje de dos nuevas capacidades la Herencia y la Composicioacuten

Por herencia (Inheritance) se entiende la capacidad de poder crear nuevas clases a partir de alguna anterior de forma que las nuevas heredan las caracteriacutesticas de sus ancestros (propiedades y meacutetodos) Se trata por tanto de la capacidad de crear nuevos tipos de datos a partir de los anteriores Una caracteriacutestica especial de la herencia es que si se cambia el comportamiento de la clase antecesora (tambieacuten llamada padre base o super) tambieacuten cambiaraacute el comportamiento de las clases derivadas de ella (descendientes)

Como puede deducirse faacutecilmente la herencia establece lo que se llama una jerarquiacutea de clases del mismo aspecto que el aacuterbol genealoacutegico de una familia Se entiende tambieacuten que estos conceptos representan niveles de abstraccioacuten que permiten acercar la programacioacuten a la realidad del mundo fiacutesico tal como lo concebimos Por ejemplo entendemos que un motor eleacutectrico deriva de la clase general de los motores de la cual derivan tambieacuten los de gasolina diesel vapor etc y que sin dejar de ser motores cada subclase tiene sus caracteriacutesticas peculiares

Por supuesto que no tendriacutea ninguacuten sentido utilizar la herencia para crear simplemente un cloacutenico de la clase base En realidad como en el ejemplo de la carta circular la herencia se emplea como un primer paso (partir de algo existente) para a continuacioacuten perfilar los comportamientos o datos que queremos pulir en la nueva versioacuten de la clase Como lo que principalmente interesa al usuario de una clase es su interfaz son justamente algunos aspectos de esta interfaz los que se modifican al objeto de adecuar la nueva subclase a las necesidades especiacuteficas del caso Por lo general esta modificacioacuten de la interfaz se consigue de dos formas

1 Antildeadiendo propiedades yo meacutetodos que no existiacutean en la clase base 2 Sobrescribiendo propiedades del mismo nombre con distintos comportamientos (sobrecarga yo

polimorfismo)

Aunque la herencia es uno de los pilares de la POO tiene tambieacuten sus inconvenientes Por ejemplo dado que el compilador debe imponer ciertas caracteriacutesticas en tiempo de compilacioacuten sobre las clases creadas por herencia esto resulta en cierta rigidez posterior Sin embargo como hemos visto una de sus ventajas es la reutilizacioacuten del coacutedigo

La composicioacuten (tambieacuten llamada herencia muacuteltiple) es la segunda viacutea para crear nuevas clases a partir de las existentes Por composicioacuten se entiende la capacidad que presenta la POO de ensamblar un nuevo tipo (clase) cuyos elementos o piezas son otras clases Es posible declarar clases derivadas de las existentes especificando que heredan los miembros de una o maacutes clases antecesoras Siguiendo con el siacutemil de la carta circular la composicioacuten equivaldriacutea a escribirla reutilizando trozos de cartas anteriores Es claacutesico el ejemplo de sentildealar que podriacuteamos crear una clase coche declarando que tiene un motor y cuatro ruedas

bastidor aire acondicionado etc elementos estos pertenecientes a la clase de los motores de las ruedas los bastidores y los sistemas de climatizacioacuten respectivamente Este sistema tiene tambieacuten sus ventajas e inconvenientes pero es muy flexible ya que incluso pueden cambiarse los componentes en tiempo de ejecucioacuten

sect2 Resumen

Como resumen de este raacutepido repaso podemos sentildealar que la Programacioacuten Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas entre las que destaca la reutilizacioacuten del coacutedigo A los acadeacutemicos les gusta decir que se sustenta en cuatro columnas a las que ya hemos hecho referencia

Encapsulamiento Poder separar la interfaz de una clase de su implementacioacuten o dicho en otras palabras no es necesario conocer los detalles de coacutemo estaacuten implementadas las propiedades para poder utilizarlas Los objetos funcionan a modo de caja negra en la que estaacuten empaquetados los datos y las instrucciones para su manipulacioacuten de las que conocemos solo lo necesario para utilizarla

Herencia Crear nuevos elementos a partir de los existentes de forma que heredan las propiedades de sus ancestros Existen dos clases de herencia simple y muacuteltiple

Sobrecarga Posibilidad de crear diferentes meacutetodos dentro de una clase que comparten el mismo nombre pero que aceptan argumentos diferentes y se comporten de forma distinta seguacuten la naturaleza de estos argumentos ( 441a)

Polimorfismo Es una caracteriacutestica que resulta de gran ayuda en programacioacuten pues facilita la claridad y consistencia del coacutedigo aunque es un concepto bastante geneacuterico (y frecuentemente malinterpretado) Se conoce con este nombre el hecho de que un meacutetodo tiene el mismo nombre y resulta en el mismo efecto baacutesico pero estaacute implementado de forma distinta en las distintas clases de una jerarquiacutea

12 El lenguaje C++

Learn not just the hows but the whys too Greg Comeau [7]

sect1 Generalidades

C++ es un lenguaje imperativo orientado a objetos derivado del C [1] En realidad un superconjunto de C que nacioacute para antildeadirle cualidades y caracteriacutesticas de las que careciacutea El resultado es que como su ancestro sigue muy ligado al hardware subyacente manteniendo una considerable potencia para programacioacuten a bajo nivel pero se la han antildeadido elementos que le permiten tambieacuten un estilo de programacioacuten con alto nivel de abstraccioacuten

Nota estrictamente hablando C no es un subconjunto de C++ de hecho es posible escribir coacutedigo C que es ilegal en C++ Pero a efectos praacutecticos dado el esfuerzo de compatibilidad desplegado en su disentildeo puede considerarse que C++ es una extensioacuten del C claacutesico La definicioacuten oficial del lenguaje nos dice que C++ es un lenguaje de propoacutesito general basado en el C al que se han antildeadido nuevos tipos de datos clases plantillas mecanismo de excepciones sistema de espacios de nombres funciones inline sobrecarga de operadores referencias operadores para manejo de memoria persistente y algunas utilidades adicionales de libreriacutea (en realidad la libreriacutea Estaacutendar C es un subconjunto de la libreriacutea C++)

Respecto a su antecesor se ha procurando mantener una exquisita compatibilidad hacia atraacutes por dos razones [2] poder reutilizar la enorme cantidad de coacutedigo C existente y facilitar una transicioacuten lo maacutes fluida posible a los programadores de C claacutesico de forma que pudieran pasar sus programas a C++ e ir modificaacutendolos (hacieacutendolos maacutes ++) de forma gradual De hecho los primeros compiladores C++ lo que

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 5:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

bastidor aire acondicionado etc elementos estos pertenecientes a la clase de los motores de las ruedas los bastidores y los sistemas de climatizacioacuten respectivamente Este sistema tiene tambieacuten sus ventajas e inconvenientes pero es muy flexible ya que incluso pueden cambiarse los componentes en tiempo de ejecucioacuten

sect2 Resumen

Como resumen de este raacutepido repaso podemos sentildealar que la Programacioacuten Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas entre las que destaca la reutilizacioacuten del coacutedigo A los acadeacutemicos les gusta decir que se sustenta en cuatro columnas a las que ya hemos hecho referencia

Encapsulamiento Poder separar la interfaz de una clase de su implementacioacuten o dicho en otras palabras no es necesario conocer los detalles de coacutemo estaacuten implementadas las propiedades para poder utilizarlas Los objetos funcionan a modo de caja negra en la que estaacuten empaquetados los datos y las instrucciones para su manipulacioacuten de las que conocemos solo lo necesario para utilizarla

Herencia Crear nuevos elementos a partir de los existentes de forma que heredan las propiedades de sus ancestros Existen dos clases de herencia simple y muacuteltiple

Sobrecarga Posibilidad de crear diferentes meacutetodos dentro de una clase que comparten el mismo nombre pero que aceptan argumentos diferentes y se comporten de forma distinta seguacuten la naturaleza de estos argumentos ( 441a)

Polimorfismo Es una caracteriacutestica que resulta de gran ayuda en programacioacuten pues facilita la claridad y consistencia del coacutedigo aunque es un concepto bastante geneacuterico (y frecuentemente malinterpretado) Se conoce con este nombre el hecho de que un meacutetodo tiene el mismo nombre y resulta en el mismo efecto baacutesico pero estaacute implementado de forma distinta en las distintas clases de una jerarquiacutea

12 El lenguaje C++

Learn not just the hows but the whys too Greg Comeau [7]

sect1 Generalidades

C++ es un lenguaje imperativo orientado a objetos derivado del C [1] En realidad un superconjunto de C que nacioacute para antildeadirle cualidades y caracteriacutesticas de las que careciacutea El resultado es que como su ancestro sigue muy ligado al hardware subyacente manteniendo una considerable potencia para programacioacuten a bajo nivel pero se la han antildeadido elementos que le permiten tambieacuten un estilo de programacioacuten con alto nivel de abstraccioacuten

Nota estrictamente hablando C no es un subconjunto de C++ de hecho es posible escribir coacutedigo C que es ilegal en C++ Pero a efectos praacutecticos dado el esfuerzo de compatibilidad desplegado en su disentildeo puede considerarse que C++ es una extensioacuten del C claacutesico La definicioacuten oficial del lenguaje nos dice que C++ es un lenguaje de propoacutesito general basado en el C al que se han antildeadido nuevos tipos de datos clases plantillas mecanismo de excepciones sistema de espacios de nombres funciones inline sobrecarga de operadores referencias operadores para manejo de memoria persistente y algunas utilidades adicionales de libreriacutea (en realidad la libreriacutea Estaacutendar C es un subconjunto de la libreriacutea C++)

Respecto a su antecesor se ha procurando mantener una exquisita compatibilidad hacia atraacutes por dos razones [2] poder reutilizar la enorme cantidad de coacutedigo C existente y facilitar una transicioacuten lo maacutes fluida posible a los programadores de C claacutesico de forma que pudieran pasar sus programas a C++ e ir modificaacutendolos (hacieacutendolos maacutes ++) de forma gradual De hecho los primeros compiladores C++ lo que

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 6:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

haciacutean en realidad era traducir (preprocesar) a C y compilar despueacutes [3] (las consecuencias se dejan sentir todaviacutea en el lenguaje 142)

Por lo general puede compilarse un programa C bajo C++ pero no a la inversa si el programa utiliza alguna de las caracteriacutesticas especiales de C++ Algunas situaciones requieren especial cuidado Por ejemplo si se declara una funcioacuten dos veces con diferente tipo de argumentos el compilador C invoca un error de Nombre duplicado mientras que en C++ quizaacutes sea interpretado como una sobrecarga de la primera funcioacuten (que sea o no legal depende de otras circunstancias)

Como se ha sentildealado C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo) ademaacutes no nacioacute como un ejercicio acadeacutemico de disentildeo Se trata simplemente del sucesor de un lenguaje de programacioacuten hecho por programadores (de alto nivel) para programadores lo que se traduce en un disentildeo pragmaacutetico al que se le han ido antildeadiendo todos los elementos que la praacutectica aconsejaba como necesarios con independencia de su belleza o purismo conceptual (Perfection in some language theoretical sense is not an aim of C++ Utility is [6]) Estos condicionantes tienen su cara y su cruz en ocasiones son motivo de ciertos reproches por parte de sus detractores en otras estas caracteriacutesticas son precisamente una cualidad De hecho en el disentildeo de la Libreriacutea Estaacutendar C++ ( 51) se ha usado ampliamente esta dualidad (ser mezcla de un lenguaje tradicional con elementos de POO) lo que ha permitido un modelo muy avanzado de programacioacuten extraordinariamente flexible (programacioacuten geneacuterica)

Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases algunas de sus extensiones tienen aplicacioacuten fuera del contexto de programacioacuten con objetos (fuera del aacutembito de las clases) de hecho muchos aspectos de C++ que pueden ser usados independientemente de las clases [5]

Del C se ha dicho Por naturaleza el lenguaje C es permisivo e intenta hacer algo razonable con lo que se haya escrito Aunque normalmente esto es una virtud tambieacuten puede hacer que ciertos errores sean difiacuteciles

de descubrir ( Shildt) Respecto al C++ podriacuteamos decir otro tanto pero hemos de reconocer que su sistema de deteccioacuten de errores es mucho maacutes robusto que el de C por lo que algunos errores de este seraacuten raacutepidamente detectados

Desde luego C++ es un lenguaje de programacioacuten extremadamente largo y complejo cuando nos adentramos en eacutel parece no acabar nunca Justo cuando aprendemos un significado descubrimos que una mano negra ha antildeadido otras dos o tres acepciones para la misma palabra Tambieacuten descubrimos que praacutecticamente no hay una regla sin su correspondiente excepcioacuten Cuando aprendemos que algo no se puede hacer hay siempre alguacuten truco escondido para hacerlo y cuando nos dicen que es un lenguaje fuertemente tipado (Strong type checking) resulta completamente falso

A pesar de todo ha experimentado un extraordinario eacutexito desde su creacioacuten De hecho muchos sistemas operativos [4] compiladores e inteacuterpretes han sido escritos en C++ (el propio Windows y Java) Una de las razones de su eacutexito es ser un lenguaje de propoacutesito general que se adapta a muacuteltiples situaciones Para comprobar el eacutexito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la paacutegina que mantiene el Dr Stroustrup al respecto wwwresearchattcom

Tanto sus fervientes defensores como sus aceacuterrimos detractores han hecho correr riacuteos de tinta ensalzando sus cualidades o subrayando sus miserias aunque todo el mundo parece estar de acuerdo en que es largo y complejo Ha servido de justificacioacuten para el disentildeo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C y Java por ejemplo) y una de sus uacuteltima incorporaciones las plantillas ( 412) ha sido origen de un nuevo paradigma de programacioacuten (metaprogramacioacuten)

En mi opinioacuten cualquier lenguaje de propoacutesito general que como C++ permita tocar ambos mundos la programacioacuten de bajo nivel y altos niveles de abstraccioacuten resultaraacute siempre e inevitablemente complejo Ocurre lo mismo con los lenguajes naturales que son tambieacuten extraordinariamente complejos (esto lo saben

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 7:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

bien los gramaacuteticos) Cualquier comunicacioacuten entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores A pesar de lo cual la comunicacioacuten exacta y sin ambiguumledades entre dos personas no resulta faacutecil

sect2 Consejos para mejorar el rendimiento

Lo mismo que en su ancestro en el disentildeo del C++ primoacute sobre todo la velocidad de ejecucioacuten del coacutedigo [4] Tanto uno como otro representan los ejecutables maacutes raacutepidos que se pueden construir para una maacutequina y circunstancias determinadas En este sentido la uacutenica alternativa de mejora es la codificacioacuten manual el pulido de determinadas rutinas (o de todo el coacutedigo) en ensamblador aunque evidentemente esto es impracticable para aplicaciones medianamente grandes a no ser que se disponga de todos los recursos y tiempo del mundo

Con todo a pesar de ser un lenguaje intriacutensecamente raacutepido y de que los compiladores modernos son bastante inteligentes en este sentido (adoptan automaacuteticamente las decisiones que resultan en el coacutedigo de ejecucioacuten maacutes eficiente) es mucho lo que puede hacer el programador para favorecer esta rapidez con solo adoptar algunas sencillas precauciones Estos son los consejos

Use enteros (int) con preferencia sobre cualquier otro tipo de variable numeacuterica En especial en los contadores de bucles Las operaciones con enteros son del orden de 10 a 20 veces maacutes raacutepidas que las de nuacutemeros en coma flotante

Use operadores incremento y decremento ++-- ( 491) Use variables de registro en especial en los bucles criacuteticos sobre todo si son anidados ( 418b) Use aritmeacutetica de punteros frente a subiacutendices de matrices ( 422) En problemas de computacioacuten numeacuterica recuerde que el caacutelculo de funciones trascendentes es por lo

general muy lento Use referencias para argumentos y valores devueltos en funciones antes que objetos por valor (

423) Al definir clases utilice al miacutenimo las funciones virtuales ( 144 4118a) asiacute como los

punteros a funciones-miembro ( 421g) o Tenga en cuenta lo sentildealado respecto al rendimiento al tratar deo Sustituciones inline en funciones definidas por el usuario ( 446b)

Preste atencioacuten al modo de uso de aquellas funciones de libreriacutea que se presentan en dos versiones ( 51 Funciones y macros)

Los compiladores modernos permiten fijar que criterio de optimizacioacuten seraacute dominante La velocidad de ejecucioacuten o el tamantildeo Tanto Borland C++ ( 143) como MS Visual C++ utilizan la misma convencioacuten de llamada para este propoacutesito (opciones -O2 o -O1 respectivamente) Por su parte GNU gcc dispone de varias opciones de optimizacioacuten En particular la opcioacuten -Os adopta las medidas tendentes a reducir el tamantildeo del coacutedigo resultante

Nota Aparte de las decisiones de optimizacioacuten que puedan adoptar automaacuteticamente los compiladores y las reglas de precaucioacuten anteriores las modernas suites ofrecen herramientas de anaacutelisis que permiten conocer de forma objetiva como es la utilizacioacuten de recursos dentro del programa de forma que se puedan adoptar precauciones en las zonas que resulten maacutes costosas y concentrar nuestros esfuerzos de optimizacioacuten en la zonas donde resulten maacutes provechosos El compilador GNU cpp dispone de la utilidad gcov que ofrece estadiacutesticas para analizar el rendimiento del coacutedigo Entre otros datos

Coacutemo se ejecuta cada liacutenea de coacutedigo Queacute liacutenea se estaacute ejecutando actualmente Cuanto tiempo consume cada seccioacuten de coacutedigo Posibilidad de anaacutelisis a nivel de fichero o de funcioacuten

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 8:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

121 Leacutexico y conceptos fundamentales

Este ha sido mi uacuteltimo curso Me acabo de jubilar despueacutes de cerca de 40 antildeos dedicado a la ensentildeanza A pesar de la poca consideracioacuten que mi profesioacuten ha tenido econoacutemica y socialmente acabo con la misma ilusioacuten con la que comenceacute E igualmente convencido de la trascendencia de la tarea de educar Soacutelo me duele un poco el comprobar la menor eficacia que eacutesta ha tenido estos uacuteltimos antildeos

iquestCuaacuteles han sido las causas Ni la mentalidad hedonista que rehuye cualquier tipo de sacrificio ni el permisivismo de los padres que satisfacen todos los caprichos de los hijos ni los planes de estudios que se fundamentan en una visioacuten luacutedica de la educacioacuten ni las poliacuteticas educativas con pretensiones de progresismo que priman el uniformismo sobre la buacutesqueda de la excelencia han favorecido en absoluto la cultura del esfuerzo imprescindible en cualquier proceso personal de mejora como es la educacioacuten Federico Goacutemez Pardo en La voz del Lector de El Confidencial Digital (22-06-2006) ECD

sect1 Presentacioacuten

Creo que buena parte de la dificultad del principiante respecto a algunos conceptos del lenguaje C++ y de muchas otras aacutereas de la ciencia informaacutetica proviene de un conocimiento incompleto o vago de algunos conceptos fundamentales En realidad se trata de una cuestioacuten semaacutentica de conocer el significado exacto de algunas palabras de disponer de un vocabulario miacutenimo que sirva de soporte para entender el resto Ocurre con frecuencia que los textos informaacuteticos estaacuten plagados de teacuterminos que supuestamente son de uso comuacuten pero que en realidad no lo son tanto y cuyo significado tampoco estaacute claramente explicado en ninguacuten sitio Se dan por sabidos pero las maacutes de las veces el estudiante es incapaz de verbalizar correctamente su significado Es importante que este corpus miacutenimo sea conocido sin ambiguumledades de forma que los conceptos construidos sobre eacutel no tengan fisuras y resulten de una solidez conceptual a toda prueba

Estas cuestiones semaacutenticas son evidentemente el objeto fundamental de los gramaacuteticos y de los puristas del lenguaje (aunque sean lenguajes artificiales como los de programacioacuten) de forma que en el caso del C++ la primera preocupacioacuten del Estaacutendar es definir sin ambiguumledad una serie de teacuterminos Introducireacute aquiacute algunos de los que creo maacutes importantes en la seguridad de que su conocimiento atantildee no solo al lenguaje C++ sino al acerbo cultural de cualquier interesado en esta disciplina

sect2 Algunos conceptos

RTFM Siglas por las que se conoce un principio universal y de gran intereacutes en la ciencia informaacutetica actual [5]

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento ( 14) Seguacuten el DRAE (Diccionario de la Real Academia Espantildeola de la Lengua) un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solucioacuten de un problema [4] En informaacutetica se utiliza en el sentido de un conjunto ordenado y finito de instrucciones que gobiernan el comportamiento de una maacutequina para conseguir un comportamiento determinado Las instrucciones se expresan en un lenguaje artificial (inventado conscientemente por el hombre) denominado lenguaje de programacioacuten

Al llegar a cierto grado de madurez y universalidad algunos lenguajes son estandarizados lo que significa que un comiteacute internacional ( 1) se encarga de establecer sus reglas de uso En el caso de los lenguajes (naturales o artificiales) estas reglas constituyen lo que se denomina su gramaacutetica El lenguaje C++ alcanzoacute oficialmente esta madurez y universalidad en 1989 de forma que a partir de entonces el Estaacutendar C++ establece la gramaacutetica del lenguaje que nos ocupa

Aunque todos los lenguajes de programacioacuten tienen su Gramaacutetica el enfoque respecto a la misma variacutea grandemente de unos a otros En ciertos casos como en C++ estas reglas son tremendamente estrictas lo que tiene sus pros y sus contras Por ejemplo una gramaacutetica riacutegida permite afinar mucho en los matices de lo que deseamos hacer manipular los conceptos (principalmente los datos) con gran precisioacuten y ser

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 9:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

advertidos de posibles errores involuntarios Pero hay que estar muy atento a los detalles del coacutedigo y hasta que no se tiene cierta praacutectica los mensajes de aviso y errores del compilador pueden desesperar a cualquiera

Otro extremo estaacute representado por los lenguajes de sintaxis maacutes o menos borrosa Por ejemplo JavaScript o Perl en los que el compilador o inteacuterprete pretende adivinar queacute se supone que queremos hacer Este comportamiento se conoce como DWIM (Do what I mean) [7]

La gramaacutetica se concreta en una serie de reglas y condiciones aunque puede haber otras Por ejemplo de estilo Las que imprescindiblemente debe cumplir un programa C++ para ser correcto son de dos clases semaacutenticas (de significado) y sintaacutecticas (de forma 131a) Justamente es el contenido de estas normas lo que hace que un programa C++ sea distinto de un programa Java o Fortran por ejemplo Las reglas sintaacutecticas son muchas pero comienzan por las que definen el alfabeto del lenguaje Es decir el conjunto de grafos que pueden utilizarse para escribir su coacutedigo

C++ permite utilizar un alfabeto de 96 caracteres ASCII en la escritura de sus programas De ellos 91 son los caracteres graacuteficos (representables por un grafo) que se incluyen en la tabla los cinco restantes son caracteres no representables Espacio tabulacioacuten horizontal tabulacioacuten vertical salto de formato y nueva liacutenea

Caracteres graacuteficos del alfabeto C++a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

La norma C++ establece que cuando en un programa no se respetan las formas (reglas sintaacutecticas) el compilador debe lanzar un mensaje de error o indicacioacuten de que no entiende lo que queremos decir Por ejemplo el caso de que olvidemos el punto y coma al final de una sentencia Sin embargo con las reglas semaacutenticas no ocurre siempre asiacute El estaacutendar distingue dos tipos de reglas de significado diagnosticables y no diagnosticables En cuanto a las primeras denominadas reglas de significado diagnosticable (Diagnosable semantic rules) la Norma establece que en caso de infraccioacuten el compilador enviaraacute al menos un mensaje de error En el caso de las segundas no se requiere esta exigencia

Nota en principio todo el conjunto de reglas semaacutenticas definidas en el Estaacutendar pueden considerarse de significado diagnosticable a excepcioacuten de aquellas que tienen una indicacioacuten expliacutecita de que no necesitan diagnoacutestico

Las reglas estaacuten definidas de modo que cuando se establece una condicioacuten diagnosticable y la forma del programa no cumple este requisito deberaacute generarse un mensaje de error correspondiente Sin embargo cuando se establece un requisito diagnosticable para un dato y este no se cumple durante la ejecucioacuten el Estaacutendar no establece ninguacuten comportamiento especial para el programa

Comportamiento dependiente de la implementacioacuten Cuando el comportamiento de un programa correcto con datos correctos depende de la implementacioacuten Este comportamiento debe estar documentado en cada implementacioacuten

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 10:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Comportamiento indefinido Es el comportamiento de un programa en aquellas circunstancias o situaciones para las que el Estaacutendar no especifica un comportamiento especiacutefico Seriacutea el caso del comportamiento en runtime de un programa que recibe datos incorrectos Observe que seguacuten lo indicado al principio muchos casos de programas erroacuteneos no generan un comportamiento indefinido sino un aviso de diagnoacutestico

Implementacioacuten Un compilador concreto para una plataforma determinada

Liacutemites de implementacioacuten Restricciones impuestas a los programas por una implementacioacuten

Programa correcto (Well-formed) Programa C++ construido de acuerdo con las reglas sintaacutecticas de este lenguaje con reglas de semaacutentica diagnosticable y que sigue la regla de una sola definicioacuten ( 412) Un programa incorrecto (Ill-formed) es el que no sigue los condicionantes anteriores

Un identificador es un conjunto de caracteres alfanumeacutericos de cualquier longitud que sirve para identificar las entidades del programa Los identificadores pueden ser combinaciones de letras y nuacutemeros y cada lenguaje tiene sus propias reglas que definen como pueden estar construidos ( 322 Identificadores C++)

Nota algunas combinaciones de caracteres las denominadas palabras-clave (Keywords) tienen un significado especiacutefico para el lenguaje y no pueden ser utilizadas en otro contexto ( 321)

Generalmente los identificadores se introducen en el programa para designar una entidad entonces se dice de ellos que son un nombre C++ permite utilizar el mismo identificador para designar entidades diferentes a condicioacuten de que esteacuten en aacutembitos ( 413) diferentes o que sean funciones con distinto nuacutemero yo tipo de argumentos

Nota otro tipo especial de identificadores lo constituyen las etiquetas en vez de representar entidades sirven para significar sentencias [1] Se utilizan para identificar el destino en sentencias de salto ( 4104)

La introduccioacuten de un nombre en el programa puede efectuarse mediante alguna de estas formas

Si el nombre representa a una entidad mediante una declaracioacuten ( 412) Si el nombre representa a una sentencia (es una etiqueta) mediante una sentencia etiquetada (

4101) o una instruccioacuten de salto goto [2]

Que un mismo nombre utilizado en dos unidades de compilacioacuten designe o no a una misma entidad depende del tipo de enlazado que tenga el identificador en cada una de ellas ( 144)

Cuando compilador encuentra un identificador en un programa supone que es un nombre o una etiqueta y antes de realizar el parsing ( 14) intenta determinar a que entidad representa Esta operacioacuten que asocia sin ambiguumledad cada nombre con una declaracioacuten de dicho nombre se denomina buacutesqueda de nombres (Name-lookup) Si al final del proceso no ha aparecido la declaracioacuten correspondiente entonces el programa es incorrecto (Ill-formed )

Cuando el identificador corresponde a una funcioacuten puede ocurrir que el Name-lookup asocie un mismo nombre con maacutes de una declaracioacuten Es el caso de funciones sobrecargadas en las que un mismo nombre corresponde a varias definiciones de la misma funcioacuten En estos casos despueacutes de esta primera buacutesqueda tiene lugar otro proceso denominado de resolucioacuten de sobrecarga (Overload resolutioacuten 441a) en el que se intenta averiguar a que definicioacuten concreta corresponde el identificador

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 11:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

El proceso de buacutesqueda de nombres sigue un conjunto relativamente extenso de reglas que cubren todas las posibilidades que pueden presentarse ademaacutes existen modificadores que alteran la forma de esta buacutesqueda los denominados especificadores o modificadores de acceso Ver en la hoja adjunta una somera descripcioacuten del proceso ( Name-lookup)

El concepto de entidad es muy amplio corresponde a un valor clase elemento de una matriz variable funcioacuten miembro de clase instancia de clase enumerador plantilla o espacio de nombres del programa (maacutes detalles en 411)

Un objeto es una entidad a la que corresponde una zona de almacenamiento [3] razoacuten por la que se dice de ellos que tienen existencia real o fiacutesica Los objetos son introducidos en el programa mediante una declaracioacuten y creados mediante una definicioacuten ( 412) Gozan de una serie de propiedades que vienen definidas desde el momento de su creacioacuten entre ellas estaacute la duracioacuten de su almacenamiento que tiene influencia en su ciclo vital (Lifetime) y puede ser de tres tipos estaacutetica dinaacutemica y automaacutetica ( 415) Otra propiedad no menos importante de los objetos es su tipo que tambieacuten viene determinado desde el momento de su creacioacuten ( 22)

Las entidades del programa pueden tener otros atributos o propiedades cuya comprensioacuten es igualmente importante direccioacuten (Lvalue) y valor (Rvalue) Sus caracteriacutesticas se detallan en el apartado correspondiente ( 21) pero adelantemos aquiacute que Rvalue se asigna al concepto de valor algo que tenga valor es un Rvalue (o tiene esta propiedad) Por su parte Lvalue se asimila al concepto de direccioacuten espacio de almacenamiento que pueda recibir un valor [6]

Una entidad puede tener uno o ambos de estos atributos Por ejemplo

char func ()

char c = 5

const int k = 2 + 3

La funcioacuten func puede ser considerada un Rvalue en el sentido que devuelve un valor tambieacuten la variable c la constante k o la expresioacuten 2 + 3 pueden ser consideradas Rvalues porque tienen o representan un valor

Tanto la variable c como la constante k son tambieacuten Lvalues en el sentido que ambas disponen de una direccioacuten y un espacio de almacenamiento correspondiente (que en el primer caso puede ser alterado y en segundo no) Sin embargo ni la funcioacuten func ni las expresioacutens 5 o 2 + 3 pueden considerarse como tales porque no les corresponde una direccioacuten o espacio de almacenamiento donde pueda colocarse un Rvalue En este contexto tiene sentido decir que un Lvalue modificable es aquel que puede cambiar el valor contenido en su almacenamiento

Una expresioacuten es un conjunto de operadores operandos y signos de puntuacioacuten que especifican una computacioacuten (suponen una secuencia de instrucciones concretas para la maacutequina) generalmente como resultado de esta computacioacuten producen un valor aunque tambieacuten como consecuencia de ella pueden producirse otros efectos denominados efectos laterales ( 131)

Inicio

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 12:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

[1] Cuando a principios de los 70 la programacioacuten no-estructurada cayoacute en descreacutedito las etiquetas que en forma de nuacutemero de sentencia acompantildeaba a estas en algunos lenguajes desaparecieron Como a pesar de todo en algunas ocasiones persiste la necesidad de acudir al denostado GOTO se introdujeron estos identificadores para sentildealar el destino de estos saltos imprescindibles (las sentencias catch del mecanismo de excepciones son otro vestigio de aquello)

[2] El lenguaje C++ establece que antes de utilizar un identificador hay que declararlo excepto en el caso de etiquetas (Labels)

[3] Observe que esta definicioacuten es maacutes amplia que la tradicional de la POO en la que un objeto es la instancia de una clase

[4] El teacutermino algoritmo y la propia ciencia del aacutelgebra son otra aportacioacuten cultural que debemos al Islaacutem Esta ciencia debe mucho a Muhammad Ibn Musa que fue miembro de la ldquoCasa de la Sabiduriacuteardquo una notable academia cientiacutefica de Bagdad en eacutepoca del califa Al-Maamun (813-833) El propio vocablo algoritmo deriva del sobrenombre Al-Khwarizmi de Ibn Musa Los algoritmos informaacuteticos siguen de cerca el concepto matemaacutetico de funcioacuten Aunque estas uacuteltimas pueden exigir un nuacutemero infinito de pasos para llegar a la solucioacuten

[5] Acroacutenimo ingleacutes de Read the fucking manual El creador del lenguaje nos informa que generalmente es una buena idea y que la F es muda (no se pronuncia) Glosario de teacuterminos C++ de Bjarne Stroustrup

wwwresearchattcom

[6] Formalmente un Lvalue es una expresioacuten que se refiere a un objeto o a una funcioacuten (una invocacioacuten a funcioacuten es un Lvalue solo si el valor devuelto es una referencia) Un Lvalue es modificable si no se refiere a una funcioacuten una matriz o un objeto constante

[7] Desde luego lo ideal seriacutea un comportamiento DWIW (Do What I Want) pero ya hemos sentildealado que los lenguajes actuales son del tipo DWIS (Do What I Say) Quizaacutes lo contrario seriacutea extremadamente peligroso

13 Estructura de un programa

The input of computation is energy and information the output is order structure extropy Kevin Kelly God Is the Machine en Wired Magazine wwwwiredcom

sect1 Sinopsis

La estructura de un programa es una cuestioacuten que puede ser abordada desde varios puntos de vista en este capiacutetulo consideramos solo dos

Componentes loacutegicos se refiere a los diversos elementos que componen una aplicacioacuten desde los maacutes complejos hasta los maacutes simples Si comparamos un programa con un edificio los elementos iriacutean desde el edificio como un todo a los ladrillos (sus elementos maacutes pequentildeos) 131

Almacenamiento se refiere a como estaacuten alojadas sus partes en la maacutequina que lo ejecuta Esta cuestioacuten puede ser abordada desde dos perspectivas

Organizacioacuten loacutegica Comprende las caracteriacutesticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 132)

Organizacioacuten fiacutesica Toma en consideracioacuten los diversos dispositivos fiacutesicos utilizados por el programa para alojarse eacutel mismo y sus datos ( 226)

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 13:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

131a Sentencias

sect1 Introduccioacuten

Al igual que los lenguajes naturales [2] los lenguajes computacionales tienen una gramaacutetica es decir un conjunto de reglas que describen los elementos que componen el lenguaje y la forma correcta de utilizarlos ( 121) Una parte de la gramaacutetica la sintaxis se ocupa de las reglas para combinar adecuadamente los elementos del lenguaje de forma que tengan un sentido En el caso de los lenguajes naturales la sintaxis ensentildea a formar las oraciones y expresar conceptos En el caso de los lenguajes computacionales ensentildea a construir sentencias que describan operaciones correctas de un computador

sect2 Sintaxis de las sentencias C++

Si nos referimos concretamente a la sintaxis sus reglas pueden ser expresadas en forma de una lista que adecuadamente interpretada describe estas reglas sintaacutecticas A continuacioacuten se expone la sintaxis permitida en C++ para las sentencias (Statements) Junto a una traduccioacuten maacutes o menos afortunada al espantildeol [1] hemos incluido el original ingleacutes para que no quepa la maacutes miacutenima ambiguumledad al respecto ya que el rigor y el purismo son imprescindibles al tratar estos aspectos gramaticales del lenguaje

Una lista de este tipo describe la sintaxis de lo que se denomina una Gramaacutetica Independiente del Contexto de Chomsky [3] En este caso define la sintaxis de una sentencia (primera entrada de la lista) Nos describe que una sentencia estaacute compuesta por los elementos que siguen en la lista (sangrados) Aquiacute tendriacuteamos que interpretar Una sentencia estaacute compuesta por una sentencia etiquetada o una sentencia compuesta o una sentencia-expresioacuten Etc A su vez las entradas sucesivas de la lista (en azul) describen la sintaxis de cada elemento Por ejemplo una sentencia compuesta estaacute formada a su vez por una lista-de-declaraciones que puede ir seguida de una lista-de-sentencias todo ello entre corchetes (el siacutembolo ltxxxgt indica que el componente xxx es opcional) A su vez la lista-de-declaraciones estaacute formada por Etc Etc

Resulta evidente que muchas de estas definiciones son recursivas Por ejemplo vemos que una lista-de-declaraciones estaacute formada por una declaracioacuten o una lista-de-declaraciones seguida de una declaracioacuten Es decir una lista-de-declaraciones puede contener a su vez otra lista de declaraciones

La lista indica que una sentencia-expresioacuten estaacute constituida por una expresioacuten seguida de un punto y coma () aunque la expresioacuten es opcional Quiere esto decir que un punto y coma aislado es una sentencia-expresioacuten sintaacutecticamente correcta en C++ es lo que se denomina sentencia-expresioacuten nula

Nota Como este libro estaacute dirigido principalmente a estudiantes de C++ que necesiten del lenguaje para sus aplicaciones praacutecticas debemos advertir aquiacute que estas cuestiones gramaticales son estrictamente formales lo que dicho sencilla y llanamente significa que de una de estas listas no es posible sacar ninguna idea concreta de queacute es una sentencia ni la menor indicacioacuten de para queacute sirven Son simplemente una indicacioacuten exquisitamente exacta de coacutemo se usan desde el punto de vista formal lo que para el programador de a pie tiene escaso o nulo valor [4]

sentencia sentencia etiquetada (labeled-statement)

sentencia compuesta (compound-statement)sentencia-expresioacuten (expression-statement)sentencia de seleccioacuten (selection-statement)sentencia de iteracioacuten (iteration-statement)sentencia de salto (jump-statement)sentencia ensamblador (asm-statement)declaracioacuten simple (declaration)bloque-intento ( 16) (try-block)

sentencia etiquetada

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 14:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

identificador sentenciacase expresioacuten constante sentenciadefault sentencia

sentencia compuesta ( 326) ltlista-de-declaracionesgt ltlista-de-sentenciasgt (ltdeclaration-listgt ltstatement-listgt) lista-de-declaraciones declaracioacuten

lista-de-declaraciones declaracioacuten lista-de-sentencias sentencia

lista-de-sentencias sentencia sentencia-expresioacuten ltexpresioacutengt sentencia ensamblador ( 410) asm tokens nueva-liacutenea (newline)

asm tokensasm tokens lttokensgt= lttokensgt

sentencia de seleccioacuten ( 4102) if ( expresioacuten ) statement

if ( expresioacuten ) statement else statementswitch ( expresioacuten ) statement

sentencia de iteracioacuten ( 4103) while ( expresioacuten loacutegica ) sentencia

do sentencia while ( expresioacuten ) for (sentencia de inicio-for ltexpresioacutengt ltexpresioacutengt) sentencia

sentencia de inicio-for sentencia-expresioacuten

declaracioacuten simple sentencia de salto ( 4104) goto identificador

continue break return ltexpresioacutengt

Inicio

[1] Debo advertir que he visto algunas traducciones del original ingleacutes principalmente realizadas en Latinoameacuterica que a los Espantildeoles nos resultan chocantes y poco afortunadas Supongo que ocurriraacute exactamente lo mismo a la inversa

[2] Lenguaje utilizado por los humanos para comunicarse entre siacute de forma natural Espantildeol Japoneacutes Ingleacutes Alemaacuten etc

[3] Noam Chomsky nacido en 1928 en Philadelphia (Pennsylvania) USA hijo de un inmigrante ruso estudioacute linguumliacutestica matemaacuteticas y filosofiacutea interesaacutendose tambieacuten por la poliacutetica pero es maacutes reconocido por sus trabajos en gramaacutetica generativa que basada en la loacutegica y en la matemaacutetica moderna fue posteriormente aplicada a la descripcioacuten de los lenguajes naturales

[4] No quisiera parecer irrespetuoso con los gramaacuteticos antes al contrario mi reconocimiento hacia ellos crece parejo con mi intereacutes por la estructura del conocimiento Lo que quiero decir es que los nintildeos aprenden a pedir chocolate antes de dominar correctamente las estructuras formales del lenguaje y que mucha gente nace vive y muere sin tener la mas miacutenima dificultad de comunicacioacuten con sus conciudadanos a pesar de no tener absolutamente ninguna idea de la gramaacutetica formal de su idioma Naturalmente que los lenguajes naturales son mucho maacutes duacutectiles que los artificiales pero a pesar de ello creo que la analogiacutea sirve para ilustrar la idea que quiero transmitir

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 15:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

132 Almacenamiento

Nota en este capiacutetulo tratamos algunos aspectos loacutegicos del almacenamiento de un programa en una computadora (coacutedigo y datos) En el capiacutetulo 226 se ampliacutean algunos conceptos relativos al almacenamiento de los datos que incluyen detalles sobre el soporte fiacutesico utilizado

sect1 Preaacutembulo

Los aspectos concretos de almacenamiento de un programa dependen de la plataforma no existe un modelo uacutenico Por ser con mucho el maacutes extendido nos referiremos aquiacute al modelo de almacenamiento tiacutepico de un programa ejecutable estaacutendar (no una libreriacutea dinaacutemica [0] ) en el entorno Windows 32 Modelo que salvo algunos detalles puede aplicarse a otras plataformas modernas

sect2 El proceso de carga

En el entorno Windows-32 cuando el Sistema carga un ejecutable (fichero-imagen) desde la memoria externa (disco) se inicia un proceso bastante complejo hasta que sus distintos moacutedulos que aquiacute se llaman segmentos quedan alojados en las posiciones de memoria asignadas por el Sistema

Nota Los distintos segmentos no necesariamente resultan contiguos entre siacute pero las entidades de cada segmento siacute estaacuten dispuestas de forma contigua dentro de ellos

Para entender el proceso recordemos que la maacutequina no entiende de conceptos tales como a = b + 1 para el procesador no existen las variables a o b En consecuencia la actuacioacuten combinada del compilador y el linker debe reducir la expresioacuten anterior a algo como copia en el registro R el contenido de las n posiciones de memoria a partir de la posicioacuten x (direccioacuten de la variable b) suacutemale una unidad y copia el resultado en n posiciones de memoria a partir de la posicioacuten z (direccioacuten que corresponderaacute a partir de ahora a la variable a) Toda esta informacioacuten se encuentra codificada en binario en el fichero imagen pero el problema es que el enlazador no puede conocer de antemano en queacute posiciones de memoria seraacute cargado el programa para su ejecucioacuten (en realidad puede ocupar posiciones distintas en cada ejecucioacuten) En consecuencia las posiciones x y z consignadas en el fichero imagen no son posiciones absolutas sino relativas a una posicioacuten inicial que seraacute asignada por el Sistema en el momento de la carga

La consecuencia final es que ademaacutes del acomodo en memoria de los distintos moacutedulos la utilidad de carga debe recalcular las direcciones contenidas en la imagen sumaacutendoles un desplazamiento inicial (offset) seguacuten el punto de inicio del segmento correspondiente Recuerde que en el ejecutable no existen identificadores (nombres) solo direcciones de memoria Es frecuente utilizar la siguiente terminologiacutea

Direccioacuten base BA (Base Address) de un fichero imagen cargado en memoria es la direccioacuten de inicio

Direccioacuten virtual relativa RVA (Relative Virtual Address) de un objeto en un fichero imagen es el valor de su direccioacuten despueacutes de cargado en memoria menos la direccioacuten base del fichero imagen

Direccioacuten virtual VA (Virtual Address) de un objeto en un fichero imagen cargado en memoria es el valor de su direccioacuten La razoacuten de que se denomine virtual es porque el Sistema Operativo crea un espacio de direcciones distinto para proceso que corre en el sistema Este espacio es independiente de la memoria fiacutesica ya que puede utilizar memoria virtual (en disco)

La disposicioacuten final de los moacutedulos en memoria sigue un esquema como el de la figura pero en un SO moderno no debe pensarse en la imagen cargada en memoria como un todo indivisible De hecho el segmento de coacutedigo es bastante

Montoacuten local

(local heap)Pila

(Stack)Datos estaacuteticos no

inicializados

Datos estaacuteticos inicializados

Coacutedigo del programa

(code segment)

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 16:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

independiente del de datos (en la figura lo hemos separado deliberadamente) Puede a su vez estar constituido por un solo trozo o por varios que pueden ser cargados en memoria de forma no simultanea solo cuando se necesitan (carga bajo demanda) Ademaacutes puede ocurrir que los distintos segmentos obtengan distintos permisos de uso por parte del Sistema Operativo Por ejemplo la aplicacioacuten propietaria puede tener permiso de solo lectura (read-only) sobre el segmento de coacutedigo y de lectura-escritura para el resto Sin embargo en las libreriacuteas dinaacutemicas (compartidas) el segmento de coacutedigo puede tener autorizacioacuten de lectura para cualquier proceso que lo solicite

sect3 Segmento de coacutedigo

En la parte maacutes baja del espacio ocupado por la aplicacioacuten se situacutea el coacutedigo del programa denominado tambieacuten segmento de coacutedigo (Code segment) contiene el coacutedigo (algoritmo) ejecutable y todos los valores que han podido ser resueltos en tiempo de compilacioacuten como es el caso de algunas constantes que no reciben un Lvalue Recordemos que en esta zona estaacute el coacutedigo de todas las funciones (incluyendo las funciones-clase 4115) y que los punteros-a-funcioacuten sentildealan precisamente direcciones de este segmento

En realidad no necesariamente existe un segmento de coacutedigo para cada instancia del programa en ejecucioacuten Por razoacuten de eficiencia y economiacutea de espacio existen casos como el de las mencionadas libreriacuteas dinaacutemicas (DLLs) en los que varias instancias de un mismo programa comparten el mismo segmento de coacutedigo (por supuesto cada instancia tiene su propio segmento de datos) Cuando ocurre esto se dice que el coacutedigo es reentrante y puede ser utilizado simultaacuteneamente por varias instancias sin peligro de corrupcioacuten debido precisamente a la independencia de los datos de cada una de ellas

sect4 Segmento de datos

Donde termina el segmento de coacutedigo comienza una zona destinada a datos es el denominado segmento de datos (Data segment) o memoria local aunque tampoco debe pensarse en el segmento de datos como un todo de tamantildeo fijo e indivisible Estaacute organizado en cuatro subzonas que no necesariamente son contiguas (puede que lo sean) con caracteriacutesticas particulares y distintas en funcioacuten del tipo de dato y coacutemo son manejados por el programa Durante el proceso de carga el Sistema les asigna el espacio necesario dentro de la memoria total disponible A continuacioacuten cuando se inicia el proceso estas zonas son inicializadas

Las zonas de datos estaacuteticos permanecen constantes en tamantildeo a lo largo de la vida del programa precisamente porque aquiacute se guardan variables y constantes cuyo tamantildeo es conocido en tiempo de compilacioacuten Pero la pila y el montoacuten pueden variar de tamantildeo durante la ejecucioacuten porque guardan objetos que son conocidos en runtime En el primer caso (la pila) porque ahiacute se guardan los valores de las funciones y en el caso de la invocacioacuten de funciones con gran nivel de anidamiento ( 446b) esta estructura puede crecer indefinidamente En el caso del montoacuten puede ocurrir que en tiempo de ejecucioacuten el proceso demande maacutes memoria para datos persistentes espacio que maacutes adelante puede ser liberado de nuevo (sect34 ) En ambos casos el tamantildeo de estas zonas puede aumentar y disminuir y consecuentemente la memoria total demandada al Sistema por el proceso en ejecucioacuten

Nota piense que un Sistema Operativo moderno asigna espacio seguacuten demandan sus aplicaciones [4] Cuando no hay memoria interna disponible la simula mediante un mecanismo de memoria virtual ( H51) que utiliza el disco para estos menesteres Teoacutericamente el Sistema puede proporcionar memoria a una aplicacioacuten mientras exista espacio en disco pero tambieacuten puede prevenirse que una aplicacioacuten no pueda asignar memoria por encima de un cierto valor (HEAPSIZE 144a)

La subzona que le corresponde a un dato concreto depende de las siguientes caracteriacutesticas

Que el dato sea conocido en tiempo de compilacioacuten o en runtime Que el dato sea persistente (estaacutetico) o se destruya cuando el programa sale del bloque en que fue

definido (automaacutetico)

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 17:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Nota algunas caracteriacutesticas de los elementos descritos en este capiacutetulo por ejemplo su tamantildeo pueden ser establecidos mediante las oacuterdenes oportunas al enlazador (Linker 14) Ver al respecto Fichero de definicioacuten ( 144a)

sect41 Datos estaacuteticos

Son objetos cuya vida se extiende durante todo el programa Tienen existencia semaacutentica y fiacutesica (disponen de espacio de almacenamiento) antes que el programa inicie su ejecucioacuten y terminan al finalizar este Corresponden a entidades declaradas fuera de cualquier funcioacuten (aacutembito de fichero) o de aacutembito de funcioacuten que han sido declaradas estaacuteticas Pueden ser de cualquier tipo y se almacenan en una zona especial del segmento de datos Seriacutean el caso de los objetos sentildealados en el ejemplo

static int x = 12 Estaacutetica iniciada

static int y Iacutedem no iniciada

int X = 10 Ok tambieacuten estaacutetica iniciada

int Y Iacutedem no iniciada

void foo (int x)

static int n1 = 22 Estaacutetica iniciada

static int n2 Estaacutetica no iniciada

Nota aparte de los estaacuteticos existe otro tipo de datos persistente que son almacenados en otro sitio y declarados de modo distinto Son los objetos del montoacuten que se describen maacutes adelante Aparte de la zona de almacenamiento y su forma de declaracioacuten se diferencian de los estaacuteticos en que aunque son de duracioacuten indefinida esta es iniciada y cancelada por el programador a voluntad Resulta asiacute que desde el punto de vista de la persistencia en los programas C++ se distinguen tres tipos de entidades

Objetos automaacuteticos Se almacenan en la pila y tienen duracioacuten de bloque de sentencia Se dice de ellos que tienen almacenamiento dinaacutemico

Objetos estaacuteticos Tienen la misma duracioacuten que el programa Se dice de ellos que tienen almacenamiento estaacutetico

Objetos del montoacuten Tienen duracioacuten entre dos instantes a voluntad del programador el momento de su creacioacuten y el de su destruccioacuten Se dice de ellos que tiene almacenamiento asignado (Allocated storage)

sect41a Datos estaacuteticos inicializados

Esta primera zona contiene datos estaacuteticos inicializados Es decir que reciben un valor expliacutecito en el coacutedigo del programa Suelen ser cadenas literales y entidades numeacutericas aunque pueden ser de cualquier tipo Es tambieacuten el caso de objetos estaacuteticos (instancias de clases) cuya inicializacioacuten corre a cargo del constructor correspondiente Por ejemplo los iostreams de la Libreriacutea Estaacutendar C++ de ES ( 53)

sect41b Datos estaacuteticos no inicializados

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 18:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Anaacutelogos a los anteriores pero sin inicializacioacuten Hemos indicado que en cualquier caso dispongan de inicializacioacuten expliacutecita o no los objetos estaacuteticos tienen existencia fiacutesica antes que se inicie la ejecucioacuten del programa A este respecto el Estaacutendar establece que todas las variables estaacuteticas que no hubiesen sido inicializadas se inicializan a 0 cuando el segmento de datos es creado en memoria

Nota Cuando en los textos informaacuteticos se dice coloquialmente guardar datos en el segmento se refieren a alguna de estas dos zonas de datos estaacuteticos

sect42 Pila (Stack)

Es un aacuterea muy importante manejada directamente por la UCP para alojar datos durante la ejecucioacuten del programa Su nombre deriva de su propio mecanismo de funcionamiento Es un almaceacuten de datos contiguos del tipo LIFO (Last In First Out 18) Frecuentemente es comparada con una pila de platos el uacuteltimo en ser colocado es el primero en ser retirado

Se usa para muchas cosas por ejemplo aquiacute se almacenan las variables locales automaacuteticas y los datos involucrados en el mecanismo de invocacioacuten de funciones de forma que si se utilizan muchas de estas invocaciones forma anidada o recursiva la pila crece En algunos sistemas la pila y el montoacuten son contiguos y el crecimiento desmesurado de la pila puede llegar a sobrescribir el aacuterea inferior del montoacuten

Maacutes informacioacuten al respecto en ( 446b Carga y descarga de funciones)

Los movimientos en el stack son generalmente raacutepidos a veces basta una simple instruccioacuten del procesador para almacenar o borrar algo en la pila Los objetos colocados en ella se asocian a una duracioacuten automaacutetica El teacutermino se refiere a que es el compilador el que determina cuando se destruyen El lenguaje C++ se caracteriza por hacer un uso extensivo de la pila (muchos objetos son automaacuteticos por defecto) y el mecanismo de invocacioacuten de funciones se basa en su utilizacioacuten Decimos que C++ es un lenguaje orientado a la pila

La localizacioacuten y desalojo de variables de la pila se realiza de forma automaacutetica (son decisiones tomadas por el compilador) no obstante la directiva register ( 418b) permite indicar que algunas variables que normalmente iriacutean en esta zona sean alojadas en los registros del procesador

Precisamente este automatismo hace que la llamada expliacutecita al destructor de objetos que hayan sido construidos en esta zona sea extremadamente peligroso ya que si se realiza antes de que el objeto salga de aacutembito el destructor seraacute llamado de nuevo cuando sea liberado el marco de la pila correspondiente a dicho aacutembito A cambio la pila presenta la comodidad que supone la destruccioacuten automaacutetica de los objetos alojados en ella cuando salen de aacutembito (con la liberacioacuten de la memoria correspondiente) lo que supone que no hay peligro de peacuterdidas inadvertidas porque el programador olvide destruir el objeto Es el siguiente caso

class MiClase

un aacutembito cualquiera

MiClase objeto1

Ok objeto1 es destruido al llegar a este punto

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 19:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

sect43 Montoacuten local (Local heap)

Es un aacuterea fija de memoria asignada en runtime por las rutinas de inicio antes de que comience la ejecucioacuten de main ( 444) Se usa para la asignacioacuten dinaacutemica de memoria Por ejemplo cuando pedimos al programa que asigne memoria mediante malloc o cuando creamos un nuevo objeto con el operador new ( 4920) Por razoacuten de su origen y comportamiento a los objetos almacenados es esta zona se les denomina objetos del montoacuten (Heap objects) de memoria dinaacutemica (Dynamic memory) o que estaacuten en almacenamiento libre (Free store)

Las asignaciones de memoria del montoacuten son generalmente maacutes lentas que las de pila Ademaacutes los objetos situados en este aacuterea tienden a ser persistentes [3] se mantienen hasta que el programador decide su destruccioacuten con la liberacioacuten consiguiente de la memoria previamente asignada por ejemplo con una llamada al destructor de una clase la funcioacuten free o la palabra delete

Nota esta lentitud en el manejo de los objetos del montoacuten es determinante en el rendimiento del programa de forma que la agilidad total de un compilador dependen grandemente de su eficacia en el manejo de la memoria dinaacutemica

El uso de la pila o del montoacuten supone una eleccioacuten de prioridades entre velocidad de creacioacuten de liberacioacuten de almacenamiento y automatismo frente a un mayor control En algunas circunstancias estos asuntos son de tener en cuenta Puede ser conveniente sacrificar la flexibilidad y automatismo (que ofrece la pila) porque prefiramos controlar exactamente el tamantildeo y tiempo de vida de un objeto (cualidades que ofrece el montoacuten)

En C claacutesico existen varias funciones de libreriacutea que permiten asignar y rehusar espacio en el montoacuten son las funciones malloc( ) calloc( ) realloc( ) y free( ) que estaacuten tambieacuten disponibles en C++ aunque este tiene un sistema propio de maacutes faacutecil uso con las palabras clave new y delete

sect431 Inconvenientes del montoacuten

El mecanismo proporcionado por C++ para manejo de esta zona de memoria es muy simple podemos afirmar que baacutesicamente se limita a asignar memoria con new y a rehusarla con delete Sin embargo esta simplicidad paga un precio Existen dos inconvenientes que pueden causar grandes problemas y quebraderos de cabeza a los programadores C++ Nos referimos a los peligros de peacuterdidas y de fragmentacioacuten de memoria

El primero se presenta cuando el programador olvida rehusar alguacuten trozo de memoria previamente asignado cuando ya no es necesario Como el compilador no tiene por siacute mismo noticia de la duracioacuten de los objetos alojados en el montoacuten es el programador el que debe ocuparse de su destruccioacuten cuando no sean ya necesarios De lo contrario si se olvida de hacerlo se produciraacuten peacuterdidas de memoria zonas de memoria no utilizadas pero que el programa las considera no utilizables Es el caso del siguiente ejemplo

class MiClase

un aacutembito cualquiera

MiClase obj1Ptr = new MiClase

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 20:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Peligro peacuterdida irremediable de memoria a menos que se

incluya la sentencia delete obj1Ptr antes del corchete de cierre

No piense el lector que puede curarse faacutecilmente de este peligro teniendo simplemente buena memoria es decir acordaacutendose de destruir todos los objetos previamente creados Existen circunstancias insidiosas contra las que se requiere cierta perspicacia y entrenamiento Para caer en la trampa pueden bastar estas inocentes sentencias (ver una explicacioacuten en 323f)

char a=Capitulo-1char b=Capitulo-2

a=b

En otros casos el motivo de la peacuterdida es un poco maacutes sofisticado (ver ejemplo 4112d2)

Como consecuencia las peacuterdidas misteriosas de memoria son muy frecuentes en los programas C++ En especial el uso de punteros en procesos de loacutegica muy intrincada puede ser una auteacutentica pesadilla en cuanto a su depuracioacuten Aunque raros existen algunos programas comerciales que ayudan al programador en la investigacioacuten de este tipo de problemas son denominados Leakage detectors en la literatura inglesa [1] Ademaacutes la Libreriacutea Estaacutendar C++ ha adoptado tambieacuten alguna medida al respecto (Punteros inteligentes 4122b1)

Nota en algunos lenguajes como JAVA o C donde al contrario que en CC++ la velocidad no es un asunto primordial esto se evita con el recolector de basura (GC Garbage collector) que se ocupa de liberar esta memoria cuando comprueba que no seraacute maacutes necesaria Sin embargo esta comodidad tiene un costo en tiempo de ejecucioacuten Aunque C++ permite que uno pueda construir su propio recolector de basura [2] no es una caracteriacutestica incluida en el lenguaje de forma estaacutendar porque como hemos sentildealado en muacuteltiples ocasiones la rapidez de ejecucioacuten es una de sus premisas de disentildeo

El segundo inconveniente es la fragmentacioacuten cuando se solicitan y rehuacutesan sucesivamente muchos trozos de memoria En estos casos puede ocurrir que en alguacuten momento no exista un trozo de memoria contigua suficientemente grande como para alojar un objeto de un tamantildeo determinado (algo parecido a lo que ocurre con la fragmentacioacuten de disco)

La solucioacuten al problema son los denominados compactadores del montoacuten (Heap compactor) que en algunos lenguajes se preocupan de mantener juntos y contiguos los trozos ocupados manteniendo contigua la zona libre Naturalmente esto tiene tambieacuten su costo en tiempo de proceso pues requiere que mientras se realizan los movimientos de bloques de memoria (que se realiza en un hilo -thread- de segundo plano 17) se congele la actividad del programa en especial el uso de punteros a tales zonas que deben ser reasignados despueacutes de los movimientos Para conseguirlo la memoria se utiliza a traveacutes de los denominados manejadores de memoria (Memory handles) y del mencionado mecanismo de bloqueo que alterna la actuacioacuten del compactador con la posible utilizacioacuten de punteros

Para mitigar los problemas antes mencionados existen libreriacuteas comerciales para C++ bajo el nombre geneacuterico de gestores de memoria (Memory managers) Son herramientas de runtime que ayudan a prevenir y detectar algunos errores corrientes en el uso del montoacuten Por ejemplo escribir maacutes allaacute del final de la memoria correspondiente a un objeto olvidar destruirlo o intentar borrarlo dos veces [5]

sect432 En realidad hay varios montones (heaps) seguacuten se considere la cuestioacuten a nivel local (de

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 21:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

aplicacioacuten) o a nivel global (del Sistema Operativo) El mecanismo de funcionamiento (para BC++) y la nomenclatura utilizada en cada caso son como sigue

Local heap (montoacuten local) al que hemos hecho referencia zona de memoria disponible solo para nuestra aplicacioacuten o libreriacutea

El maacuteximo de bloques de memoria que pueden situarse en el montoacuten local es de 64K menos el tamantildeo de la pila (stack) y de las zonas de variables globales (estaacuteticas) Por esta razoacuten el montoacuten local estaacute mejor adaptado para bloques de memoria pequentildeos (de 256 bytes o menos) El tamantildeo por defecto para el montoacuten local es 8 K pero puede cambiarse (en el fichero DEF)

Observe que este liacutemite se refiere a 64K bloques no 64K Bytes De hecho los bloques pueden ser todo lo grandes que se necesite siempre que exista memoria disponible Cuando la memoria fiacutesica se agota el sistema signa memoria virtual pero cuando el montoacuten es muy grande el sistema se ralentiza notablemente ya que el meacutetodo de asignacioacuten de memoria dinaacutemica del compilador es baacutesicamente un mecanismo de buacutesqueda de un bloque libre (del tamantildeo adecuado para la demanda del momento) en una cadena en la que se alternan zonas libres y ocupadas

Global heap (montoacuten global) zona de memoria disponible para todas las aplicaciones

Aunque el montoacuten global puede contener bloques de cualquier tamantildeo estaacute pensado para bloques grandes (de 256 bytes o maacutes) Bajo el sistema Windows en modos normal y 386 extendido cada bloque del montoacuten global necesita de un extra de al menos 20 bytes En este sistema existe ademaacutes una limitacioacuten de 8192 bloques para el montoacuten global de los cuales solo algunos estaacuten disponibles para una aplicacioacuten determinada

Nota el compilador BC++ puede subdividir bloques del montoacuten global en trozos maacutes pequentildeos a fin de reducir la posibilidad de alcanzar el liacutemite del sistema ( HeapLimit y HeapBlock)

heap suballocator Cuando en un programa el manejador del montoacuten (heap manager) asigna un bloque grande de memoria simplemente asigna un bloque del montoacuten global (global heap) utilizando la rutina GlobalAlloc de Windows

En cambio cuando se asigna un bloque pequentildeo el heap manager de BC++ asigna un bloque grande del montoacuten global y lo subdivide en bloques maacutes pequentildeos seguacuten la necesidad El mecanismo de reasignacioacuten de estos bloques pequentildeos reutiliza todo el espacio disponible antes de que el manejador del montoacuten tenga que asignar un nuevo bloque del montoacuten global (que a su vez es nuevamente subdividido)

Inicio

[0] Existe un tipo especial de ejecutable las Libreriacuteas Dinaacutemicas ( 144b) cuyo esquema de almacenamiento tiene ciertas peculiaridades respecto a lo aquiacute sentildealado

[1] A tiacutetulo de ejemplo podemos citar a Rational httpwwwrationalcom que produce herramientas de ayuda al desarrollo entre las que se encuentra PurifyPlus un depurador que permite controlar este tipo de problemas Tambieacuten Valgrind httpdeveloperkdeorg~sewardj un depurador de memoria de coacutedigo abierto (GPL) para x86-GNULinux que tambieacuten puede ser utilizado en desarrollos Windows

[2] Desde luego la construccioacuten de un recolector de basura automaacutetico para un programa C++ no es una tarea para principiantes pero existen algunas versiones comerciales suficientemente probadas Ver al respecto el sitio de Hans-J Boehm Paacutegina personal de Hans la seccioacuten dedicada a Garbage collection puede ser un buen punto de inicio para los interesados en el tema Tambieacuten puede consultarse la paacutegina de The Code Proyect en la que se muestra uno de estos programas wwwcodeprojectcom

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 22:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

[3] Aunque en la literatura inglesa se utilizan con profusioacuten los teacuterminos memoria dinaacutemica memoria libre y objetos dinaacutemicos para designar a los objetos almacenados en esta zona de memoria las expresiones nos parecen desafortunadas Por esta razoacuten a los objetos alojados en el montoacuten preferimos designarlos como objetos persistentes ya que a nuestro juicio este calificativo describe mejor las caracteriacutesticas de duracioacuten de tales objetos

[4] Gran parte del trabajo de un Sistema Operativo estaacute relacionado con el manejo de la memoria Su eficiencia en este sentido tanto para el manejo de la memoria interna (RAM) como la externa (sistema de ficheros utilizado) determina de forma principaliacutesima la calidad total del mismo

[5] Se afirma que el 99 por ciento de los denominados errores de memoria (Memory bugs) son causados por una mala utilizacioacuten de objetos en el montoacuten

14 Proceso de creacioacuten de un programa

Regla de oro de la programacioacuten Nunca estaacute terminado del todo iexcliexcl

sect1 Sinopsis

Programming is the art of expressing solutions to problems so that a computer can execute those solutions Bjarne Stroustrup Programming Principles and Practice Using C++

Escribir un programa es establecer el comportamiento de una maacutequina mediante una serie de algoritmos que definiraacuten su funcionamiento En el estado actual de la ciencia este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador Generalmente estas instrucciones que aquiacute se denominan coacutedigo fuente vienen acompantildeadas de algunos datos en forma de texto o imaacutegenes contenidas en uno o varios ficheros denominados ficheros de recursos (resources) Sin embargo las instrucciones y recursos solo pueden ser utilizadas por la maacutequina despueacutes de un proceso de traduccioacuten que es realizado por la propia maacutequina (puede ser distinta de la que ejecuta el programa) El proceso exige que el coacutedigo fuente sea transformado en una nueva secuencia de instrucciones seguacuten un nuevo sistema de codificacioacuten (el lenguaje maacutequina) y que los recursos adopten una disposicioacuten particular Este conjunto de instrucciones y datos que constituyen el denominado ejecutable corresponden a acciones concretas y datos que pueden ser entendidas ejecutadas y utilizados por la maacutequina

En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real o de una abstraccioacuten que hemos imaginado y es de tipo geneacuterico Se pretende que la maacutequina se comporte como una funcioacuten que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacioacuten de las condiciones de entrada

sect2 Presentacioacuten del problema

Hay bastante literatura sobre programacioacuten en general a los acadeacutemicos les gusta hablar de Teoriacutea de la Programacioacuten y mucha gente se ha dedicado a especular sobre el tema Incluso hay modas al respecto [4] Es posible confeccionar una lista de las caracteriacutesticas que debe y no debe tener un buen programa (incluyendo la del Jefe que solo tiene dos puntos Que esteacute para ayer que salga barato) El propio Stroustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa Seguacuten eacutel existen dos respuestas Saber que se quiere decir y Praacutectica Imitar buenos escritores Maacutes adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento

Por supuesto seriacutea un atrevimiento por mi parte contradecir tan docta opinioacuten pero puestos a filosofar me gustariacutea puntualizar que el verdadero problema estaacute en el segundo punto de la segunda respuesta la primera aunque ciertamente importante me parece la verdad de Perogrullo Siempre me ha parecido que

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 23:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

programar (programar bien) tiene mucho de arte Me parece que debe ocurrir como con la muacutesica seguramente muchos pueden decir que debe tener una buena ejecucioacuten de violiacuten pero imitar a Paganini debe ser harina de otro costal Seguramente los profesores de armoniacutea saben que debe tener y no tener una buena sinfoniacutea pero otra cosa debe ser imitar a Mozart

Bajando a la tierra tampoco se trata aquiacute de hacer Paganinis de la programacioacuten C++ (ya me gustariacutea para miacute) el mensaje que quisiera transmitir es doble El contenido en un viejo Refraacuten Espantildeol La Universidad no presta lo que la naturaleza no da Como suena un poco duro antildeadireacute un consuelo para los que somos menos dotados un proverbio que leiacute hace tiempo en liacutenea con la respuesta de Stroustrup Por el dinero del trabajo los Dioses lo venden todo

A continuacioacuten se comentan brevemente los pasos imprescindibles en la creacioacuten de un programa C++ Vaya por delante que las anotaciones de los puntos sect3 sect4 y sect5 son opinioacuten del que suscribe basados en la propia experiencia por tanto totalmente subjetivos y opinables

sect3 Comprender el problema

Custom development is that murky world where a customer tells you what to build and you say are you sure and they say yes and you make an absolutely beautiful spec and say is this what you want and they say yes and you make them sign the spec in indelible ink nay blood and they do and then you build that thing they signed off on promptly precisely and exactly and they see it and they are horrified and shocked and you spend the rest of the week reading up on whether your EampO insurance is going to cover the legal fees for the lawsuit youve gotten yourself into or merely the settlement cost Or if youre really lucky the customer will smile wanly and put your code in a drawer and never use it again and never call you back Joel on Software Set Your Priorities wwwjoelonsoftwarecom

As more became known about what people wanted to do with computer it became clear that there would always be increasingly more complex problems to solve A part of that realization is the realization that our ability to accurately describe the problem determines the ability for the problem to be solved Most people are incapable of clearly and precisely articulating -- to the level necessary -- the problems that theyre trying to solve This is a problem that is getting larger and not smaller Robert Bogue (Jupitermedia Corp) en Breaking Down Software Development Roles

Often a problem is only fully understood through the process of programming a solution for it Bjarne Stroustrup Programming Principles and Practice Using C++

Esta es la tiacutepica obviedad que a veces se pasa por alto Hemos dicho que escribir un programa es establecer el comportamiento de una maacutequina parece lo maacutes natural del mundo enterarse primero de cual es ese comportamiento Tener una imagen mental lo maacutes clara posible de las caracteriacutesticas de lo que pretendemos modelar Esta cuestioacuten es lo que los teoacutericos denominan el espacio del problema What domain en la literatura inglesa

A esta fase se la suele denominar anaacutelisis y mi consejo particular es que despueacutes de una primera toma de contacto el segundo paso sea definir de la forma maacutes detallada posible el principio y el final del problema Es decir cual es la informacioacuten de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacioacuten final y en que soporte se proporcionaraacute no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analoacutegico-digital nos suministra una determinada sentildeal (por citar alguacuten ejemplo)

Normalmente en ambas cuestiones tiene mucho que decir el cliente [2] es lo que se llama especificacioacuten el resto (lo que hay entre los datos de entrada y la salida) debe rellenarlo el programador Generalmente si se tienen bien definidos ambos extremos se tiene resuelta la mitad del problema cuando se tengan disentildeados los ficheros se tendraacuten dos terceras partes -ver a continuacioacuten- Este sistema tiene ademaacutes la ventaja de

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 24:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

poner inmediatamente de manifiesto las indefiniciones de partida a veces los clientes no saben exactamente queacute desean y hay que ayudarles a centrar el problema

Dentro de esta fase tiene especialiacutesima importancia el tema de los liacutemites esto se refiere al orden de magnitudes que se manejaraacuten iquestDe que rango seraacuten las magnitudes numeacutericas iquestPodraacuten adoptar valores negativos iquestHay informacioacuten alfanumeacuterica iquestComo son de largas estas cadenas Especialmente si el programa implica disentildeo de archivos (como es casi seguro) iquestCual podraacute llegar a ser su tamantildeo dentro de la vida del programa Si se manejan ficheros u objetos binarios iquestComo son de grandes iquestQue concepto tiene el cliente de los que seriacutea raacutepido o lento (iquestmilisegundos minutos horas) En esta fase sea especialmente precavido y no se crea a pieacute juntillas todo lo que le digan (intente hacer de abogado del diablo)

Como postre disentildee las liacuteneas maestras de una estrategia de recuperacioacuten de errores de ejecucioacuten incluyendo que haraacute con los no recuperables (errores fatales) Piense por ejemplo que si alguacuten diacutea lo llaman para ver que ha pasado quizaacutes le interese disponer de un volcado de texto ASCII en el disco con una descripcioacuten del estatus del programa como parte de las funciones de salida ( 15) Hoy diacutea cuando se empieza a hablar de frigoriacuteficos que avisaraacuten de que faltan provisiones o de lavadoras que avisaraacuten al teacutecnico si se estropean no estariacutea de maacutes que sus programas estuviesen a la altura de las circunstancias

sect4 Disentildear los ficheros y moacutedulos

Si el programa debe utilizar ficheros que no vengan impuestos (ya existentes) y suponiendo que todo lo anterior esteacute suficientemente claro este es el momento de hacerlo Ponga por escrito la especificacioacuten de tales ficheros incluyendo el nombre que daraacute a las variables y en su caso el que tendraacuten en el disco o almacenamiento externo Esto puede concretarse quizaacutes a la definicioacuten de algunas estructuras ( 45) En esta fase es posible que tenga que repreguntar alguna cosa que se pasoacute por alto

Teniendo ya una imagen maacutes o menos clara de lo que haraacute su programa si eacuteste es mediano o grande es posible que todaviacutea tenga que realizar una labor previa antes de ponerse a escribir el coacutedigo disentildear a grandes rasgos cuales seraacuten los moacutedulos del programa moacutedulos que se corresponderaacuten aproximadamente con la distribucioacuten del coacutedigo en ficheros fuente independientes Quizaacutes tenga que decidir tambieacuten si algunas partes apareceraacuten como libreriacuteas [1] Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4111)

Esta fase es especialmente importante en el caso de programas muy grandes cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos moacutedulos En estos casos el anaacutelisis la especificacioacuten la subdivisioacuten en partes (con sus especificaciones particulares) y la asignacioacuten de estas como tareas a los programadores lo habraacute realizado el jefe de programacioacuten y desarrollo

sect5 Escribir el coacutedigo

Suponiendo cumplimentados los pasos anteriores el programador estaacute en condiciones de construir una imagen mental clara de como seraacute esa conexioacuten entre la informacioacuten de entrada y la salida es lo que se denomina espacio de la solucioacuten (How domain) su forma concreta es justamente el fuente del programa que se pretende La codificacioacuten consiste justamente trasportar a papel (en el lenguaje de programacioacuten elegido) la imagen mental de esa conexioacuten

Para escribir el coacutedigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 221a) Son los siguientes [8]

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 25:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Juego de caracteres imprimibles

a b c d e f g h i j k l m n o p q r s t u v w x y zA B C D E F G H I J K L M N O P Q R S T U V W X Y Z0 1 2 3 4 5 6 7 8 9_ [ ] ( ) lt gt + ^ amp | ~ = rsquo

Caracteres no-imprimibles denominados separadores

Espacio horizontal Tabulacioacuten horizontal (TAB) Tabulacioacuten vertical (VT)

Salto de forma (FF) Nueva liacutenea (NL)

Nota Para escribir el coacutedigo solo hace falta un editor de texto plano aunque las modernas suites de programacioacuten incluyen editores especiacuteficos que estaacuten conectados con el depurador el compilador el enlazador (ver maacutes adelante) e incluso el sistema de ayudas de forma que por ejemplo pueden mostrarnos automaacuteticamente la sentencia en la que se ha producido un error de compilacioacuten o la paacutegina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente) Tambieacuten muestran en diversos colores las palabras clave los comentarios Etc Los maacutes avanzados disponen incluso de opciones que podriacuteamos calificar de inteligentes en el sentido que pueden prever cual seraacute nuestro proacuteximo movimiento en funcioacuten de la sentencia que estamos escribiendo (por ejemplo ofrecernos una lista de las propiedades y meacutetodos de una clase si nos estamos refiriendo a ella)

Durante la fase de escritura no desdentildee dos puntos

Incluir la mayor cantidad de comentarios y aclaraciones posibles Cuando se estaacute muy metido en el programa todo parece evidente pero piense que tiene que retocarlo dentro de unos antildeos quizaacutes entonces le parezca Chino y agradeceraacute haber dejado la mayor cantidad de documentacioacuten y aclaraciones al respecto Incluso si es seguro que no volveraacute a verlo piense en el sufrido programador que le seguiraacute si tiene que habeacuterselas con su coacutedigo En este sentido C++ no es precisamente COBOL aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 31) No caiga tampoco en el error de pensar que esa informacioacuten ya estaacute en la documentacioacuten escrita que le han obligado a entregar junto con los fuentes posiblemente dentro de unos antildeos Usted mismo no encuentre esos documentos

Incluir la mayor cantidad posible de rutinas y condiciones de comprobacioacuten de errores Piense que el operador es un manazas o que los datos pueden venir con alguna corrupcioacuten error de transmisioacuten etc Verifique constantemente que las condiciones son las esperadas ( 145)

Una vez que se tiene el coacutedigo fuente (en uno o varios moacutedulos) el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje maacutequina) puede hacerse siguiendo dos modelos los inteacuterpretes y los compiladores [3]

En el caso de lenguajes compilados como C++ el fichero de texto plano (ASCII 221a) que contiene el fuente del programador (con la terminacioacuten C oacute CPP) es sometido a un proceso de varias fases que terminan en la obtencioacuten del ejecutable

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 26:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

De forma geneacuterica todo este proceso se denomina compilacioacuten aunque es una generalizacioacuten un tanto incorrecta ya que la compilacioacuten propiamente dicha es solo una de las etapas intermedias Seriacutea maacutes correcto decir construccioacuten del ejecutable aunque por la extensioacuten y generalizacioacuten de su uso seguiremos utilizando el teacutermino geneacuterico compilacioacuten para referirnos a eacutel Los procesos de construccioacuten del ejecutable se esquematizan en la figura que comentamos a continuacioacuten

sect6 Preproceso

En la primera fase de la compilacioacuten un programa especial denominado make es encargado de iniciar el proceso llamando a los diversos moacutedulos que se encargan de la construccioacuten del ejecutable (en 140 se ampliacutean detalles sobre esta parte del proceso) El primero de estos moacutedulos es el preprocesador

El preprocesador ( 141) estudia el texto buscando directivas de preprocesado ( 4910) por ejemplo sentencias que pueden ser suprimidas incluye los ficheros correspondientes a las directivas include sustituye los define elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos El resultado obtenido es lo que se denomina unidad de compilacioacuten ( 142)

sect7 Anaacutelisis sintaacutectico

Puesto que el fichero fuente estaacute escrito en un lenguaje (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales) el compilador debe comprobar que estas reglas se han respetado Este anaacutelisis (Parsing) es realizado por el analizador sintaacutectico [10]

En esta fase se realizan comprobaciones como que los pareacutentesis estaacuten cerrados que no aparecen expresiones incompletas etc Para realizar esta labor el parser debe identificar los tokens ( 32) de forma que el fuente es tokenizado esto es reducido a tokens y separadores

El fuente es escaneado el analizador sintaacutectico (parser) extrae los tokens seleccionando el que coincida con la secuencia de caracteres maacutes larga posible dentro de la secuencia analizada [9] Por ejemplo la palabra clave external es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar extern (una palabra reservada) y al (que seriacutea un identificador)

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 27:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Los separadores (whitespaces) es el nombre geneacuterico dado a los espacios (32) tabulaciones verticales VT (11) horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13) Los separadores sirven para indicar donde empiezan y terminan las palabras pero despueacutes de esto cualquier separador redundante es descartado Por ejemplo las dos secuencias

int i float f

int i

float f

son leacutexicamente equivalentes y el resultado del anaacutelisis son las seis palabras siguientes

int

i

float

f

El caraacutecter ASCII espacio puede formar parte de cadenas literales (alfanumeacutericas) en cuyo caso es protegido del proceso de anaacutelisis permaneciendo como parte de la cadena Por ejemplo

char name[] = Playa Victoria

es reducido a siete tokens incluyendo una cadena literal Playa Victoria

char

name

[

]

=

Playa Victoria

sect8 Anaacutelisis semaacutentico

En lenguajes como el Ensamblador la comprobacioacuten se limita al anaacutelisis anteriormente sentildealado con esto se garantiza que el fuente original es correcto (sintaacutecticamente) es decir es un escrito correcto desde el punto de vista del lenguaje otra cosa es que tenga un sentido computacional correcto o diga tonteriacuteas incongruencias o sinsentidos [6]

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 28:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Por supuesto la meta del compilador es conseguir descubrir con anticipacioacuten (al runtime) el maacuteximo de errores posibles En los lenguajes de alto nivel esto se consigue con una cierta comprobacioacuten del sentido o significado del escrito es el denominado anaacutelisis semaacutentico (anaacutelisis del significado)

La mejor baza de que dispone C++ para esta segunda comprobacioacuten es la comprobacioacuten estaacutetica de tipos ( 22) Es decir que las variables y las operaciones entre ellas se usan correctamente esto supone verificar que las llamadas a funciones los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso Por ejemplo

int x

char func()

x = func()

En este caso la primera liacutenea declara que la variable x es tipo int (entero) la segunda declara que la funcioacuten fun devuelve un caraacutecter (char) si una liacuteneas maacutes adelante se pretende igualar la variable x con el valor devuelto por la funcioacuten el analizador semaacutentico estariacutea en condiciones de asegurar que existe una incongruencia en las pretensiones del programador generando el correspondiente mensaje de advertencia o error

sect9 Generador de coacutedigo

Todos estos tokens identificados por el analizador sintaacutectico son organizados en una estructura como las hojas de un aacuterbol A continuacioacuten el generador de coacutedigo recorre este aacuterbol traduciendo sus hojas directamente en coacutedigo de la maacutequina para la que se compila [11]

Si se solicita el compilador tambieacuten puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccioacuten por el programador (este coacutedigo es tambieacuten dependiente de la maacutequina para la que se compila y faacutecilmente entendible por el humano puede contener incluso comentarios para facilitar su lectura)

Nota Los compiladores modernos suelen incluir opciones que permiten generar coacutedigo optimizado para el tipo de procesador que se utilizaraacute Por ejemplo el compilador Borland C++ dispone de opciones que permiten generar coacutedigo optimizado para procesadores Intel de modelos especiacuteficos ( 143a) Como cabriacutea esperar el compilador GNU c++ es el que ofrece maacutes posibilidades en este sentido que incluyen el tipo de procesador dentro de una larga lista de fabricantes y dentro de estos diferentes modelos En concreto para la familias Intel i386 y x86-64 permite elegir entre 20 posibilidades diferentes

A veces despueacutes del generador de coacutedigo puede ejecutarse un optimizador (peephole optmizer) Este generador de coacutedigo seriacutea propiamente el compilador es decir el encargado de traducir algo entendible por el humano en coacutedigo maacutequina

En cualquier caso el resultado es un fichero objeto generalmente con la terminacioacuten obj o o Tambieacuten puede ordenarse al compilador que incluya en el objeto determinada informacioacuten adicional que seraacute utilizada maacutes tarde por el depurador por ejemplo los nuacutemeros de liacutenea de las sentencias Cuando se hace asiacute se habla de una compilacioacuten provisional o de depuracioacuten distinta de la que se realiza para la versioacuten definitiva (de campo) del programa en la que no se incluyen este tipo de informacioacuten que ya no es necesaria

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 29:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

sect10 Enlazado

El uacuteltimo paso en construir un ejecutable es el enlazado Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 144) Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacioacuten de los diversos moacutedulos (ficheros c) que componen el programa Ademaacutes si se han utilizado funciones o clases de libreriacutea [1] (como es casi seguro) el enlazador (Linker) es el programa encargado de incluir los moacutedulos adecuados en el fichero ejecutable final

Asiacute pues la funcioacuten primordial del enlazador es resolver todas las referencias que puedan existir en el programa es decir que cada invocacioacuten a un valor o a una funcioacuten corresponda una direccioacuten donde se encuentra el recurso correspondiente y que esteacuten todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el Sistema Operativo

Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable libreriacuteas de enlazado dinaacutemico (en Windows se denominan DLLs) En cuyo caso el enlazador tambieacuten incluiraacute las direcciones y convenciones de llamada adecuadas para que puedan ser traiacutedos a ejecucioacuten desde el programa principal

Por uacuteltimo el enlazador se encarga de insertar en el ejecutable un trozo de coacutedigo especial el moacutedulo inicial que es el encargado de iniciar la ejecucioacuten ( 15)

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados

sect101 Versioacuten de depuracioacuten

Se trata de una versioacuten en la que dentro del propio ejecutable se incluye informacioacuten adicional no estrictamente necesaria para la ejecucioacuten sino para la depuracioacuten (por ejemplo los nuacutemeros de liacutenea del coacutedigo fuente que corresponde a cada sentencia) Estos ejecutables permiten la ejecucioacuten en un modo especial en la que por ejemplo pueden ejecutarse las sentencias paso a paso o que el programa se detenga al llegar a diversos puntos establecidos de antemano ver el contenido de las variables el estado de la pila y otros aspectos internos muy uacutetiles cuando se intentan depurar errores de tiempo de ejecucioacuten Esto se consigue porque el programa corre bajo control de otro programa que actuacutea de controlador de la ejecucioacuten es el depurador (Debugger)

Nota El depurador puede ser en realidad un moacutedulo adicional al de inicio inserto en el ejecutable que se inicia antes que la propia funcioacuten main ( 444) de forma que puede controlar la ejecucioacuten Por esta razoacuten entre otras las versiones de depuracioacuten son mayores (en tamantildeo del fichero) que las definitivas o de campo [12]

sect102 Versioacuten de publicacioacuten

Es la versioacuten definitiva que saldraacute al puacuteblico (se entregaraacute al usuario) Se distingue de las versiones internas en que no incluye informacioacuten para depuracioacuten Es buena praacutectica incluir en cada versioacuten publicada informacioacuten sobre el nuacutemero de versioacuten del programa y de compilacioacuten (esto suele venir indicado en la siguiente forma Versioacuten xxyyzz build nnn)

Generalmente los programas sufren muchas modificaciones a lo largo de su vida (correccioacuten de errores perfeccionamientos versiones para diversas plataformas etc) y es preciso identificarlos Es costumbre hablar de versiones que se identifican por grupos de nuacutemeros separados por puntos Por ejemplo Versioacuten xxyyzz Cada fabricante de software grupo de trabajo o programador utiliza una convencioacuten establecieacutendose que tipo de cambios dan lugar a diferencias de versioacuten en el grupo de cifras xx en el yy o en el zz Generalmente se acepta que los cambios de mayor nivel (xx) representan versiones totalmente nuevas del programa que requieren incluso rescribir los manuales de uso Los cambios menores corresponden a

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 30:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

modificaciones en el grupo yy (por ejemplo utilizar otras versiones de las libreriacuteas o distinto compilador) finalmente los cambios de detalle representan modificaciones en el grupo zz Viene a representar cambios miacutenimos que no merecen una alteracioacuten del uacuteltimo grupo de cifras [7] pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado aunque sea un comentario en el fuente) Es tambieacuten costumbre incluir un uacuteltimo identificador El nuacutemero de compilacioacuten o construccioacuten (build en la literatura inglesa) es un nuacutemero progresivamente creciente para cada compilacioacuten distinta A tiacutetulo de ejemplo en la paacutegina adjunta se muestra la clasificacioacuten utilizada para las sucesiones versiones de los productos de un conocido fabricante ( Designacioacuten de versiones)

sect103 Libreriacutea

En las paacuteginas siguientes veremos que como resultado de la compilacioacuten no siempre se desea conseguir un ejecutable al menos no en el sentido tradicional del teacutermino sino una libreriacutea (de las que existen varios tipos) o un fichero objeto

En lo que respecta al lenguaje C++ existen dos tipos fundamentales Estaacuteticas y Dinaacutemicas Las primeras son colecciones de ficheros precompilados cuyo coacutedigo puede ser antildeadido a un ejecutable en el proceso de enlazado (los ficheros de la Libreriacutea Estaacutendar 5 que acompantildean a los compiladores C++ son de este tipo) Las segundas son auteacutenticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucioacuten Maacutes detalles al respecto en ( 144a)

sect11 Errores Volver al principio (rescribir el coacutedigo)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa Todos los moacutedulos involucrados en los pasos anteriores compilador analizador sintaacutectico y enlazador pueden detectar errores en nuestro coacutedigo y mostrar los mensajes correspondientes

sect111 Tipos de errores

En cuanto al momento en que se producen son baacutesicamente de tres tipos

De tiempo de compilacioacuten Se engloban aquiacute los errores detectados por preprocesador el analizador sintaacutectico y el propio compilador Los hay meramente sintaacutecticos por ejemplo un pareacutentesis no cerrado tambieacuten de tipo loacutegico por ejemplo la referencia a una variable no declarada previamente etc etc

De tiempo de enlazado Son detectados por el enlazador Por ejemplo una llamada a funcioacuten cuya definicioacuten no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como normales para buscar) tambieacuten la inversa dos funciones del mismo nombre situadas en dos moacutedulos (fuentes) distintos (la referencia aparece duplicada)

De tiempo de ejecucioacuten (runtime) Existe finalmente una uacuteltima clase de errores los que se producen cuando se ejecuta el programa son precisamente los maacutes difiacuteciles de diagnosticar y verificar sobre todo en aplicaciones grandes (los relativos a peacuterdidas misteriosas de memoria y punteros descontrolados son especialmente temibles)

sect112 Gravedad de los errores

Los errores producidos durante la compilacioacuten son de dos tipos seguacuten su gravedad

Errores fatales (Errors) Son errores graves el proceso no puede continuar y es detenido despueacutes de mostrar la informacioacuten pertinente

Advertencias (Warnings) No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 31:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

inadvertidamente (por ejemplo Una variable declarada que no se utiliza para nada maacutes) En estos casos el proceso continua y si no hay errores graves se construye un ejecutable

En todos los casos el aviso incluye indicacioacuten del fichero (fuente CCPP) el nuacutemero de liacutenea y el nombre de la funcioacuten donde se produce el error asiacute como una explicacioacuten maacutes o menos clara de su motivo En principio pueden ser cuestiones banales como haber olvidado poner un punto y coma al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes) En otros casos los mensajes son especialmente criacutepticos sobre todo para el profano pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencioacuten y entendemos su porqueacute

Recordar que todos los compiladores disponen de opciones para modificar el nuacutemero y tipo de los errores y advertencias (Warnings) que aparecen Respecto a los primeros puede instruirse al compilador para que suspenda la actividad al aparecer el primer error o que continuacutee hasta que aparezca un nuacutemero determinado de ellos Respecto a los avisos puede ordenarse que no muestre ninguno o que sea maacutes o menos benevolente en determinados aspectos Por ejemplo puede indicarse que la comprobacioacuten siga estrictamente el estaacutendar C++ y que avise de cualquier desviacioacuten al respecto (los compiladores suelen permitir ciertas peculiaridades que no son estaacutendar)

Nota La descripcioacuten e informacioacuten acerca del error o advertencia dependen de la plataforma pero hemos de sentildealar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores en especial respecto a los Warnings Por ejemplo en este sentido el Compilador Borland C++ 55 es mucho menos riguroso que el producto homoacutelogo de Microsoft cuyo sistema de verificacioacuten es con mucho superior al del primero de forma que no es infrecuente que advertencias maacutes o menos serias e incluso algunos errores advertidos por Visual C++ 60 sean totalmente ignorados por Builder A su vez los errores y advertencias sentildealados por el compilador GNU Cpp suelen ser maacutes explicativos que los sentildealados por Borland o Visual (que en este sentido son maacutes criacutepticos)

sect113 Generalidades sobre los errores de compilacioacuten

Respecto a los errores de compilacioacuten es importante hacer una advertencia al neoacutefito Con frecuencia el compilador nos informa de error en una liacutenea maacutes abajo de donde estaacute verdaderamente Por ejemplo olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres liacutenea maacutes abajo

Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha praacutectica es preferible realizar cambios pequentildeos y compilar sistemaacuteticamente despueacutes de cada uno Asiacute sabremos que el error corresponde a lo uacuteltimo que hemos tocado Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en liacuteneas siguientes Suacutebitamente nada tiene sentido para el compilador [5]

En las asignaciones del tipo

Lvalue = Rvalue

en las que intentamos asignar un valor Rvalue ( 21 que puede ser el resultado de una expresioacuten) a un Lvalue ( 21) son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspecto

Error Cannot convert xxxxx to yyyyy in function

Lo importante a resentildear aquiacute es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresioacuten de asignacioacuten

Nota En el capiacutetulo dedicado a los tipos de datos ( 22) se describe detalladamente como el compilador clasifica los objetos seguacuten su tipo

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 32:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

En las asignaciones el Lvalue debe recibir un valor de su mismo tipo Si el tipo del Rvalue no concuerda con eacutel el compilador puede intentar adecuarlo pero si esto no es posible se produce un error como el sentildealado En eacutel se nos indica que el tipo xxxxx que corresponde al Rvalue (el resultado de la expresioacuten a la derecha del operador = ) no puede ser convertido al tipo yyyyy del Lvalue

Hay que advertir que las expresiones xxxxx e yyyyy estaacuten codificadas Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++ En concreto la designacioacuten utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4914) En situaciones difiacuteciles es mucha la informacioacuten que puede obtenerse de estas expresiones si se observan detenidamente

Aunque la comprobacioacuten estaacutetica de tipos y del cumplimiento de las reglas sintaacutecticas realizada por el compilador resultan muy eficientes en lo que respecta a la deteccioacuten de errores en realidad el trabajo dista de ser completo y suficiente Existen multitud de circunstancias potencialmente erroacuteneas que son pasadas por alto En especial las relacionadas con peacuterdidas de memoria existencia de punteros descolgados bucles infinitos objetos declarados pero no utilizados y un largo etceacutetera Algunos de estos errores pueden permanecer agazapados en el coacutedigo y solo aparecer en circunstancias muy especiales incluso despueacutes de que la aplicacioacuten haya sido rodada largo tiempo sin contratiempos Muchas de estas circunstancias pueden evitarse o al menos mitigarse siguiendo ciertas pautas y recomendaciones de buena praacutectica muchas de las cuales estaacuten contenidas en la obra TC++PL de Stroustrup la mayoriacutea en forma de advertencias sobre cosas que no debe hacerse Sin embargo el problema persiste maacutexime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arceacuten y con el que es posible volarse la pierna completa

Para reforzar la calidad del coacutedigo y prevenir errores posteriores (de run-time) se han creado multitud de herramientas Entre las maacutes conocidas se encuentran las siguientes

Lint denominadas asiacute en atencioacuten a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores debugger -de run-time- aunque tambieacuten sirven para depurar el coacutedigo) comprueban la sintaxis y errores en los tipos de datos de forma maacutes concienzuda y profunda que los compiladores CC++ y avisan de gran cantidad de peligros potenciales incorrecciones desviaciones sobre las reglas universalmente aceptadas como de buena praacutectica etc Actualmente han llegado a un elevado nivel de sofisticacioacuten de forma que un buen Lint puede evitarnos muchas horas de depuracioacuten En realidad es una herramienta que no deberiacutea faltar en el taller del programador profesional

cb Esta utilidad originaria del SO AIX reformatea el coacutedigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estaacutendar de salida (stdout 53) utilizando un formateo basado en sangrados y espaciados que ayudan a interpretar la estructura del coacutedigo

cflow Esta utilidad originaria del SO AIX analiza el contenido de un fichero objeto CC++ y proporciona en la salida estaacutendar (stdout) un graacutefico de sus referencias externas

cxref Esta utilidad anaacuteloga a las anteriores analiza los fuentes CC++ y genera una tabla con todos los siacutembolos encontrados en cada fichero incluyendo los nombres de los paraacutemetros formales de las funciones (contenidos en la definicioacuten de la funcioacuten) La tabla es mostrada en el dispositivo estaacutendar de salida (stdout) e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicioacuten esteacute en el coacutedigo analizado)

Si estaacute interesado en las caracteriacutesticas y posibilidades de estos productos la mayoriacutea comerciales y algunos muy costosos aparte de la correspondiente buacutesqueda en Google existe un interesante artiacuteculo de Scott Meyers (uno de los Gurus del C++) y Martin Klaus titulado A First Look at C++ Program Analyzers en el que se repasan las cualidades y caracteriacutesticas de distintos paquetes incluyendo una evaluacioacuten de su comportamiento frente a lo que el autor considera deseable Aparecido en el nuacutemero de Febrero de 1997 del

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 33:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Dr Dobbs Journal existe una versioacuten de pre-publicacioacuten accesible on-line que es incluso maacutes completa que el artiacuteculo publicado (probablemente debido a las exigencias de maquetacioacuten de la revista) wwwaristeiacom

Uno de los productos punteros y maacutes antiguos es el de Gimpel Software wwwgimpelcom esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint La primera para Windows la segunda maacutes general para cualquier entorno que soporte un compilador C incluyendo Unix y Linux Si tiene intereacutes en comprobar maacutes de cerca el tipo de informacioacuten que proporcionan estas utilidades en el sitio de este fabricante existe una seccioacuten denominada Bug del mes (Bug of the month) en la que se exponen ejemplos de coacutedigo junto con el resultado del anaacutelisis (despueacutes de pulsar un botoacuten) Ademaacutes de suacutemamente instructivos los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto A mi entender tambieacuten pueden constituir una magniacutefica fuente de inspiracioacuten para los ensentildeantes que busquen material para ejemplo o evaluacioacuten (sed piadosos en los exaacutemenes porque algunos son realmente para niveles avanzados No se puede pretender que despueacutes de un semestre de estudio el alumno esteacute en condiciones de adivinar correctamente el bug CC++ del mes -)

sect114 Errores de ejecucioacuten

Para los errores de tiempo de ejecucioacuten se requieren estrategias especiales En principio durante la fase de comprobacioacuten inicial se tienen las ofrecidas por el depurador Praacutecticamente todos los entornos de desarrollo disponen de un depurador maacutes o menos potente y sofisticado Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional en especial porque hay errores que son praacutecticamente imposibles de diagnosticar y corregir sin su ayuda

Como se ha indicado el depurador incluye en el ejecutable un coacutedigo especial que realiza las funciones de depuracioacuten deseadas pero aparte de los que podriacuteamos denominar estaacutendar (cuyos moacutedulos son incluidos en durante la fase de enlazado del ejecutable) existen herramientas especiacuteficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias Estas herramientas realizan su trabajo durante la ejecucioacuten para lo que modifican el coacutedigo a analizar incluyendo determinados moacutedulos que les permiten controlar el desarrollo de la ejecucioacuten (se dice que instrumentan el coacutedigo) La forma de realizar esta instrumentacioacuten depende de la herramienta puede realizarse durante la compilacioacuten (compile-time) antildeadiendo coacutedigo que no aparece en el fuente durante el enlazado (link-time) durante la carga (load-time) cuando el ejecutable es acomodado en memoria o antes de la carga sobre cualquier ejecutable listo para ser usado Generalmente estas herramientas controlan la ejecucioacuten toman nota de las incidencias y finalmente proporcionan un informe de las mismas cuando la ejecucioacuten finaliza

Nota no existe una denominacioacuten unificada para este tipo de productos Quizaacutes el maacutes conocido es es BoundsChecker de Numega wwwnumegacom (actualmente aparece como Compuware) Tambieacuten puede intentar una buacutesqueda en Google bajo el epiacutegrafe Memory debugger

Despueacutes de todas las medidas preventivas ya resentildeadas cuando finalmente despueacutes de las pruebas de laboratorio damos por bueno el programa este queda merced a si mismo a la calidad de su propio mecanismo de defensa Como errar es humano los disentildeadores del C++ pensaron que a pesar de la programacioacuten maacutes cuidadosa siempre pueden presentarse circunstancias excepcionales o imprevistas Para poder hacerles frente dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones de forma que pudiese seguir todo bajo control estos recursos especiacuteficos se exponen con detalle en el capiacutetulo dedicado al Tratamiento de Excepciones ( 16)

sect12 Recursos

Ya hemos sentildealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la maacutequina y Sistema en que deba ejecutarse y que en el teacutermino Compilador incluimos todas las herramientas auxiliares enlazador libreriacuteas etc

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 34:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Por supuesto que en este sentido las plataformas comerciales en especial las versiones denominadas Enterprise ofrecen unas prestaciones inigualables incluyendo potentes depuradores disentildeo graacutefico de elementos con capacidad de arrastrar y soltar (dragg and drop) elementos y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccioacuten de determinados aspectos de las aplicaciones Por ejemplo el manejo de bases de datos o comunicaciones En esta categoriacutea podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows

En la paacutegina dedicada a los Compiladores encontraraacute algunas referencias ( Compiladores)

Si desea saber maacutes sobre aspectos relacionados con la compilacioacuten preproceso anaacutelisis sintaacutectico y semaacutentico traduccioacuten del coacutedigo etc mi consejo es que consulte Compiladores y Procesadores de Lenguajes [Jimeacutenez-04]

Inicio

[1] En el argot de programacioacuten funcioacuten de libreriacutea se refiere a un recurso prefabricado trozos de coacutedigo generalmente en forma de funciones o clases que otros han escrito que incluimos en nuestro programa La confeccioacuten de programas se parece a la construccioacuten de un edificio en el que cada vez maacutes se utilizan elementos preconstruidos (algunas veces normalizados) que facilitan y aceleran la construccioacuten Suelen ser de dos clases incluidas en el compilador (lenguaje utilizado) que en caso del C++ estaacuten incluidas en la denominada Libreriacutea Estaacutendar ( 5) y de terceras partes libreriacuteas especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que ademaacutes saben mucho sobre el tema) se han encargado de escribir y comprobar Por ejemplo libreriacuteas graacuteficas de comunicaciones estadiacutesticas para escribir coacutedigos de barras en una impresora Etc

Las modernas suites de programacioacuten C++ incluyen completiacutesimas libreriacuteas en las que estaacuten resueltas la mayoriacutea de las situaciones que habitualmente se suelen presentar en la programacioacuten normal Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo El paquete estaacutendar comprende un entorno graacutefico de programacioacuten (IDE) para Windows que incluye un potente conjunto de libreriacuteas en forma de herramientas Es un producto comercial con un precio determinado En cambio el compilador el depurador y la Libreriacutea Estaacutendar se suministran gratis Es decir se asume que el valor comercial estaacute en el entorno graacutefico integrado y en las libreriacuteas adicionales

[2] Seguramente se me ocurre lo de cliente por deformacioacuten profesional por supuesto el cliente podemos ser nosotros mismos el jefe el profesor de la asignatura Etc

[3] Con objeto de mejorar la velocidad de ejecucioacuten (tradicionalmente lenta) algunos inteacuterpretes utilizan en realidad un modelo hiacutebrido Obtienen un seudo-ejecutable intermedio mediante un preprocesado seguido de un parsing con lo que se obtiene un coacutedigo tokenizado que es el que se entrega realmente al inteacuterprete

[4] A la hora de redactar estas liacuteneas parece estar muy de moda una teacutecnica denominada Programacioacuten Extrema (eXtreme programming) cuya filosofiacutea se basa en 12 principios o mandamientos alguno tan pintoresco como el de las 40 horas semanales seguacuten el cuaacutel la mejor manera de aumentar el rendimiento es que los programadores solo trabajen 40 horas a la semana pues estaacute cientiacuteficamente demostrado que un trabajador fresco produce coacutedigo de mejor calidad que uno cansado A miacute particularmente este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondas No se aconseja utilizarlo para secar a su mascota -))

[5] Como consecuencia despueacutes de algunos antildeos de oficio los programadores suelen (solemos) ser gente un poco tocada de la azotea No cabe duda que pasar antildeos viviendo en un mundo donde no da igual un punto que una coma en un milloacuten de liacuteneas de coacutedigo termina imprimiendo caraacutecter El resultado es que el resto de la gente normal no entiende muy bien porqueacute somos tan maniaacuteticos y puntillosos en algunos

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 35:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

asuntos ya que afortunadamente (iquest) el mundo real suele ser de loacutegica maacutes borrosa (a veces tan borrosa que apenas se ve nada)

Nota Esto de la loacutegica Borrosa viene a cuento y recuerdo de un amigo Una persona de un gran talento natural que no ha tenido ocasioacuten de recibir formacioacuten acadeacutemica (es mecaacutenico y apenas ha ido a la escuela) En cierta ocasioacuten delante de unas cervezas intenteacute explicarle las diferencias entre la loacutegica binaria y la difusa (Fuzzy logic) Diacuteas despueacutes conversaba eacutel con otras personas y me sorprendioacute como introduciacutea el concepto de la loacutegica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida Solo habiacutea cambiado una palabra borrosa en lugar de difusa

[6] Las circunstancias son exactamente ideacutenticas a las que se presentan en los lenguajes naturales Tambieacuten en estos es posible construir frases sintaacutecticamente correctas pero carentes de sentido (los poliacuteticos saben mucho de esto)

[7] En esta nomenclatura una versioacuten 2410 es anterior a la 2130 que a su vez es anterior a la 123

[8] Para resolver el problema de que algunos de estos siacutembolos no aparecen en los teclados de determinados idiomas (por ejemplo la tilde ~ en los teclados espantildeoles) se recurrioacute a representarlos mediante ternas de otros caracteres los denominados trigrafos ( 323e)

[9] Esta regla de anaacutelisis es conocida como de Max Munch en realidad no es ninguacuten personaje real sino un convenio adoptado por los integrantes del primer Comiteacute de Estandarizacioacuten del lenguaje

[10] En general un parser es un programa disentildeado para analizar un documento

[11] On average each line of code in a system programming language translates to about five machine instructions compared to one instruction per line in assembly language (in an informal analysis of eight C files written by five different people I found that the ratio ranged from about 3 to 7 instructions per line in a study of numerous languages Capers Jones found that for a given task assembly languages require about 3-6 times as many lines of code as system programming languages) Programmers can write roughly the same number of lines of code per year regardless of language so system programming languages allow applications to be written much more quickly than assembly language John K Ousterhout Scripting Higher Level Programming for the 21st Century wwwtcltk

[12] Como botoacuten de muestra sentildealar que en una aplicacioacuten C++ tiacutepica Windows cuyo ejecutable resultaba de 631 KBytes en su versioacuten de campo la inclusioacuten de la informacioacuten necesaria para depuracioacuten hizo aumentar su tamantildeo hasta 3257 KBytes (Compilador GNU gcc-g++ 342 para Windows -incluido en Dev-C++ -)

FALTA PARTE ACA

142 Compilacioacuten

sect1 Sinopsis

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 36:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Hemos sentildealado ( 14) que estrictamente hablando compilacioacuten se refiere al proceso de generacioacuten de coacutedigo que sigue al preprocesado Un proceso en el que el compilador recorre la estructura de tokens generada por el analizador sintaacutectico traducieacutendolos en coacutedigo de la maacutequina para la que compila

El resultado de la compilacioacuten es un fichero objeto OBJ que contiene coacutedigo maacutequina directivas de enlazado referencias externas nombres de funciones y datos generados a partir de los ficheros-fuente

sect2 Unidad de compilacioacuten

El trabajo del compilador se efectuacutea sobre un fichero denominado unidad de compilacioacuten (Translation unit) o moacutedulo Se refiere a un fichero de coacutedigo fuente (c cpp) al que se antildeaden los ficheros include al que se suprimen las liacuteneas correspondientes a las directivas de preprocesado Es decir lo que resulta de pasar el fuente por el preprocesador

El concepto de unidad de compilacioacuten es fundamental en C++ y en el resto de lenguajes que siguen procesos de construccioacuten similares para sus ejecutables E imprescindible para comprender muchos conceptos relacionados con la visibilidad y duracioacuten de los objetos Sintaacutecticamente una unidad de compilacioacuten se define como una secuencia de declaraciones externas [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en [1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en 131a)

Unidad de compilacioacuten

Declaracioacuten externa

Declaracioacuten externa Unidad de compilacioacuten

Declaracioacuten externa

Definicioacuten de funcioacuten

Declaracioacuten

El resultado de compilar la unidad de compilacioacuten es un fichero objeto (obj o) Por lo general en los proyectos de software se utilizan varias unidades de compilacioacuten que son compiladas separadamente para despueacutes enlazarlas en uno o varios ejecutables Si como ocurre con frecuencia en proyectos grandes la funcionalidad incluida en estas unidades de compilacioacuten debe ser reutilizada muchas veces entonces no permanecen como tales ficheros obj independientes sino que se agrupan en libreriacuteas

sect3 Deformacioacuten de nombres

Cuando el compilador C++ traduce un moacutedulo en el que existen funciones los identificadores originales son cambiados por una versioacuten distorsionada que incluye de forma codificada los tipos de argumentos utilizados por la funcioacuten Esta distorsioacuten o deformacioacuten de nombres conocida tambieacuten como decoracioacuten o planchado de nombres (Name mangling) es la que hace posible la sobrecarga de funciones ( 441a) Puesto que aunque dos funciones compartan el mismo nombre si son distintos los tipos de argumentos las versiones internas (planchadas) de tales nombres son distintas

Nota la razoacuten de la decoracioacuten de nombres es de tipo histoacuterico Las primeras implementaciones de C++ eran simplemente preprocesadores que traduciacutean a C despueacutes se compilaba en este lenguaje Para resolver el problema de que C++ permite sobrecarga de funciones (diversas funciones comparten el mismo nombre pero se distinguen por el nuacutemero y tipo de sus argumentos) cosa que no es posible en C se recurrioacute a deformar los nombres de las funciones asignaacutendoles un nombre interno (para el compilador) que deriva de

[1] del tipo siguiente (ver una explicacioacuten sobre este tipo de listas en

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 37:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

su nombre en el fuente agregaacutendole datos sobre el nuacutemero y tipo de los argumentos Se consigue asiacute que el compilador pueda distinguir las diversas versiones de una funcioacuten sobrecargada

Ademaacutes de esto la decoracioacuten de nombres es un mecanismo C++ de seguridad (de comprobacioacuten de tipos) que ayuda al enlazador a comprobar si las invocaciones a funciones situadas en otros moacutedulos son correctas (respecto a la idoneidad de los argumentos utilizados) Por ejemplo en MS VC++ la funcioacuten

void Func(int i)

se transforma internamente en FuncYAXHZ

Hay que tener en cuenta que esta decoracioacuten de los nombres de las funciones no estaacute especificada por el Estaacutendar C++ de forma que es normal que dos compiladores de fabricantes distintos planchen las funciones de forma distinta (por ejemplo MS VC++ y Borland C++ Builder no lo hacen igual) El resultado es que salvo que se tomen precauciones especiales (que veremos a continuacioacuten) no estaacute garantizado que las libreriacuteas construidas con un compilador C++ funcionen con otro

sect31 Evitar el planchado de nombres

Se presentan ocasiones en que no se desea que ocurra esta distorsioacuten en el fichero que se compila Por ejemplo cuando un moacutedulo C++ se compila para ser enlazado con otros moacutedulos (de compiladores o lenguajes distintos) en los que no se utiliza este planchado (o se realiza de forma distinta) Esto ocurre en especial cuando tales moacutedulos deben ser enlazados con otros compilados en C (que no utiliza esta teacutecnica)

Para evitar el planchado se utiliza la declaracioacuten extern C en la declaracioacuten (prototipo) de la funcioacuten Esta declaracioacuten puede realizarse a tiacutetulo individual o para un grupo (bloque de enlazado E144) Por ejemplo

extern C void Cfunc(int) para una funcioacuten

extern C para un bloque de enlazado void Cfunc1(int) void Cfunc2(int) void Cfunc3(int)

extern C para todas las de un fichero de cabecera include locallibh

Todas estas formas indican al compilador que las correspondientes funcione no deben ser planchadas

Nota naturalmente lo anterior tiene un coste representado por la ausencia de posibilidad del mecanismo de sobrecarga de funciones en el moacutedulo en el que se evita la decoracioacuten de nombres

sect32 Maacutes sobre el declarador extern y algunas precisiones sobre el comportamiento del compilador ( 418d)

sect33 La declaracioacuten extern ldquoCrdquo no puede usarse con identificadores de clases ( 4112a)

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 38:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

sect34 No confundir la declaracioacuten extern C con la especificacioacuten de forma de llamada C ( 446a)

Inicio

[1] Noacutetese que la palabra externoa tiene varias connotaciones en C++ En este caso se refiere a declaraciones hechas fuera de cualquier funcioacuten que por tanto son globales al fichero (enlazado externo tiene un sentido distinto)

Proceso de desarrollo de un programa

Si se desea escribir un programa en C++ se debe ejecutar como miacutenimo los siguientes pasos

1 Escribir con un editor de texto plano un programa sintaacutecticamente vaacutelido o usar un entorno de desarrollo (IDE) apropiado para tal fin

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 39:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

2 Compilar el programa y asegurarse de que no han habido errores de compilacioacuten3 Ejecutar el programa y comprobar que no hay errores de ejecucioacuten

Este uacuteltimo paso es el maacutes costoso por que en programas grandes averiguar si hay o no un fallo praacutecticamente puede ser una tarea toteacutemica

Como ejemplo si se desea escribir un archivo con el nombre holacpp y en eacutel escribir un programa con emacs por ejemplo que es un programa de edicioacuten de textos se puede en Linux ejecutar el siguiente comando

$emacs holacpp amp

Para otros sistemas operativos u otros entornos de desarrollo no necesariamente se sigue este paso

A continuacioacuten se escribe el siguiente coacutedigo en C++Ejemplo

Aquiacute generalmente se suele indicar queacute se quiere con el programa a hacer Programa que muestra Hola mundo por pantalla y finaliza Aquiacute se situacutean todas las libreriacuteas que se vayan a usar con include que se veraacute posteriormente Las libreriacuteas del sistema son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal y la encargada de mostrar Hola Mundo sin comillas por pantalla int main(void) Este tipo de liacuteneas de coacutedigo que comienzan por son comentarios El compilador los omite y sirven para ayudar a otros programadores o a uno mismo en caso de volver a revisar el coacutedigo Es una praacutectica sana poner comentarios donde se necesiten aunque estas liacuteneas tan soacutelo sirven para ayudar al lector a visualizar el potencial de los comentarios stdcout ltlt Hola Mundo ltlt stdendl Mostrar por stdcout el mensaje Hola Mundo y comienza una nueva liacutenea return 0 Y como en este programa no se hace maacutes se termina devolviendo un 0 que en este caso quiere decir que la salida se ha efectuado con eacutexito

Mediante simple inspeccioacuten el coacutedigo parece enorme pero el compilador lo uacutenico que leeraacute para la creacioacuten del programa es lo siguienteEjemplo

include ltiostreamgt int main(void)stdcoutltltHola Mundoltltstdendlreturn 0

Como se puede observar este coacutedigo y el original no difieren en mucho salvo en los saltos de liacutenea y que los comentarios de los que se detallan posteriormente estaacuten omitidos y tan soacutelo ha quedado el esqueleto del coacutedigo legible para el compilador Para el compilador todo lo demaacutes sobra

Este es un ejemplo similar compilable en Turbo C++Ejemplo

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 40:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

include ltiostreamhgt int main(void) stdcout ltlt Hola Mundo return 0 este texto solo lo puede leer el programador

O este otro que es en parte como el lenguaje C en su versioacuten C99 esEjemplo

include ltstdiohgt include ltstdlibhgt int main(void) este texto solo lo puede leer el programador printf( Hola Mundon ) return EXIT_SUCCESS EXIT_SUCCESS es una definicioacuten que estaacute dentro de stdlibh

Nota si se usa Windows el coacutedigo es muy similarEjemplo

include ltiostreamgt int main(void) stdcout ltlt Hola Mundo ltlt stdendl stdcinget() Esto se pone a diferencia de en los otros coacutedigos por que en windows la ventana se cerraraacute suacutebitamente con stdcinget() lo que se hace es esperar hasta que el usuario pulse enter return 0

Los pasos siguientes son para una compilacioacuten en Linux o sistema operativo Unix exceptuando el sistema operativo MacOSX En Windows tampoco es aplicable

Con ctrl-x ctrl-s se guarda el archivo Ahora para generar el ejecutable del programa se compila con g++ de la siguiente forma

$ g++ holacpp -o hola

Para poder ver los resultados del programa en accioacuten se ejecuta el programa de la siguiente forma

$hola

Y a continuacioacuten se debe mostrar algo como lo siguiente

Hola Mundo

Comentarios

Cuando se escriben programas es muy uacutetil agregar comentarios que ayuden a explicar lo que realiza un programa En C++ se pueden utilizar tres tipos de comentarios al estilo C al estilo C++ y usando preprocesador

Los comentarios al estilo C se caracterizan por lo siguiente comenzar el bloque de comentarios con y terminar dicho bloque de comentarios con

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 41:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Un comentario dentro del coacutedigo al estilo C puede ser como se muestra a continuacioacuten

Este es un comentario al estilo C

Los comentarios al estilo C pueden continuar por varias liacuteneas de un mismo archivo como se muestra en el siguiente coacutedigo

Este es un comentario al estilo C que puede ocupar varias liacuteneas como se muestra a continuacioacuten

El siguiente bloque de comentarios en algunos compiladores puede provocar fallos por lo que no se recomienda su uso

Ahora el programador por accidente incluyoacute un antes de lt-- tiempo por lo que el programa tendraacute fallos

Usando el estilo de coacutedigo de C++ soacutelo pueden ocupar una liacutenea como en el siguiente coacutedigo

Este es un comentario al estilo C++

Este es el tipo de comentarios maacutes utilizados en programas en los que se usa uacutenicamente C++ por que generalmente los programadores resumen partes del coacutedigo que puedan provocar confusioacuten o sean de difiacutecil lectura para otros programadores

Una buena praacutectica de programacioacuten es pensar que se programa a sabiendas de que otro programador tal vez el lector mismo en un futuro tenga que desencriptar queacute quiso hacer ahiacute y por queacute

Otra posible forma de comentar coacutedigo es usando el preprocesador Esto se detallaraacute maacutes adelante en profundidad por ahora la parte uacutetil del preprocesador que interesa es la siguiente

if 0 Comentarios sobre el programa parte del programa Pueden ocupar muacuteltiples liacuteneas Maacutes complicado de visualizar que los comentarios CC++ endif

Este tipo de comentarios se usan rara vez Generalmente son difiacuteciles de localizar incluso para programadores experimentados que trabajan en papel y son faacuteciles de distinguir en casi cualquier IDE Es recomendable indicar que se tratan de comentarios o directamente no usarlos salvo si son grandes cantidades de comentarios Se veraacute maacutes adelante que tambieacuten puede tener otros usos

Utilizacioacuten de la consola o terminal

En los ejemplos anteriores se utilizaron stdcout stdcout es un objeto que permite escribir en la consola (la terminal en LinuxUnixMacOSX) solo se puede utilizar gracias a que se ha incluido definiciones de su uso con la liacutenea de coacutedigo include ltiostreamgt

stdcout ltlt ALGO

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 42:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Donde ALGO puede ser lo que sea que stdcout sea capaz de mostrar por consola Maacutes adelante se trata maacutes sobre el en detalle y aclarando posibles dudas que ahora puedan surgir Tambieacuten se utilizoacute stdendl esto permite que el texto se escriba en una nueva liacutenea

Un ejemplo maacutes completo sobre la escritura en consola es el siguiente Ha de tenerse en cuenta que se han eliminado algunos comentarios superfluos del primer programa debido a que ahora se estaacute tratando con maacutes detalle acerca del uso de imprimir texto en la consolaEjemplo

Programa que muestra diversos textos por consola Las libreriacuteas del sistema usadas son las siguientes include ltiostreamgt Funcioacuten main Recibe void Devuelve int Es la funcioacuten principal encargada de mostrar por consola diferentes textos int main(void) Ejemplo con una uacutenica liacutenea se muestra el uso de stdcout y stdendl stdcout ltlt Bienvenido Soy un programa Estoy en una linea de codigo ltlt stdendl Ejemplo con una uacutenica liacutenea de coacutedigo que se puede fraccionar mediante el uso de ltlt stdcout ltlt Ahora ltlt estoy fraccionado en el codigo pero en la consola me muestro como una unica frase ltlt stdendl Uso de un coacutedigo largo que cuesta leer para un programador y que se ejecutaraacute sin problemas No se recomienda hacer liacuteneas de esta manera esta forma de programar no es apropiada stdcout ltlt Un gran texto puede ocupar muchas lineas ltlt stdendl ltlt Pero eso no frena al programador a que todo se pueda poner en una unica linea de codigo y que ltlt stdendl ltlt el programa al ejecutarse lo situe como el programador quiso ltlt stdendl return 0 Y se termina con eacutexito

Se reta a compilar este coacutedigo y a observar sus resultados En este momento el lector estaacute capacitado para escribir programas que impriman por pantalla el mensaje que se quiera

Atencioacuten Se hace hincapieacute en la posibilidad de que las palabras acentuadas no se puedan mostrar en la consola Depende completamente del compilador el que se pueda ver lo siguiente

stdcout ltlt programacioacuten

Con algunos compiladores veraacute programacioacuten pero con otros puede ver incluso programaci n

Advertencia cout puede ser utilizado sin tener std de forma previa porque se puede introducir una directiva denominada using que acomoda todos los cout De otro modo habriacutea un error de compilador Este tema se trata en detalle maacutes adelante

using namespace std

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 43:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Sintaxis

Sintaxis es la forma correcta en que se deben escribir las instrucciones para el computador en un lenguaje de programacioacuten especifico C++ hereda la sintaxis de C estaacutendar es decir la mayoriacutea de programas escritos para el C estaacutendar pueden ser compilados en C++

El punto y coma

El punto y coma es uno de los simboacutelos maacutes usados en C C++ y se usa con el fin de indicar el final de una liacutenea de instruccioacuten El punto y coma es de uso obligatorio

ejemplo

clrscr() Limpiar pantalla funciona solo con la libreriacutea conio de Borland C++x = a + b

El punto y coma se usa tambieacuten para separar contadores condicionales e incrementadores dentro de un sentencia for

ejemplo

for (i=0 i lt 10 i++) cout ltlt i

Separador de bloque

Un bloque es un grupo de instrucciones contenidas entre los siacutembolos de llave izquierda y llave derecha su uso es obligatorio en la definicioacuten de funciones y opcionalmente pueden aparecer en cualquier otra parte del programa

ejemplos

aquiacute las llaves son opcionales ya que dentro del ciclo for hay solamente una instruccioacutenfor (i=0 i lt 10 i++) cout ltlt i

Espacios y tabuladores

Usar caracteres extras de espaciado o tabuladores ( caracteres tab ) es un mecanismo que nos permite ordenar de manera maacutes clara el coacutedigo del programa que estemos escribiendo sin embargo el uso de estos es opcional ya que el compilador ignora la presencia de los mismos Por ejemplo el segundo de los ejemplos anteriores se podriacutea escribir como

for (int i=0 i lt 10 i++) cout ltlt i x x++

y el compilador no pondriacutea ninguacuten reparo

Tipos primitivos

En un lenguaje de programacioacuten es indispensable poder almacenar informacioacuten para esto en C++ estaacuten disponibles los siguientes tipos que permiten almacenar informacioacuten numeacuterica de tipo entero o real

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 44:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

El modificador long

El modificador long le indica al compilador que el tipo debe utilizar maacutes bits que los normalmente utilizados por ejemplo si tenemos en una maquina de 32 bits como un Pentium de Intel normalmente de un int ocupara 32 bits pero si al declararlo un entero le antecedemos long el entero ocupa 64 bits el siguiente coacutedigo muestra como utilizar este modificador

int corto Entero de 32 bits long int largo Entero de 64 bits

El Modificador short

Similar al anterior pero indica que se deben utilizar menos bits Por ejemplo en una maacutequina de 32 bits un short int ocupa 16 bits

El Modificador unsigned

El modificador unsigned es utilizado uacutenicamente con los enteros su utilizacioacuten permite utilizar en los enteros uacutenicamente la parte positiva

int a Almacena valores entre -128 y 127unsigned int a Almacena valores entre 0 y 255

El Modificador register

Este modificador sobre una variable le indica al compilador que la variable debe almacenarse en un registro en el compilador que para el caso de los IA32 es un registro real de la propia CPU y por tanto el tiempo de acceso es maacutes raacutepido respecto a la memoria RAM Hoy en diacutea a penas se utiliza este modificador ya que los compiladores son capaces de determinar de manera oacuteptima la asignacioacuten de registros a variables del programa

El Modificador volatile

Al contrario que el modificador registrer volatile obliga al compilador a forzar el coacutedigo resultante de manera que la variable modificada con este modificador sea almacenada siempre en la memoria El efecto que tiene es que cuando la variable se modifica con otro valor dicha variable se almacena directamente en memoria y no queda localizado el valor soacutelo en el registro de la CPU como pasaba en el caso de register o en condiciones normales Un uso muy comuacuten en el que se suele emplear este modificador es para acceder a variables que estaacuten siendo utilizadas por drivers o por perifeacutericos ya que si no declaraacutesemos esta propiedad podriacutea darse el caso que la CPU usase el valor de la variable por lo que la cacheacute guarda el valor y poco despueacutes la CPU usase de nuevo dicha variable pero como eacutesta estaacute en cache la CPU coge el valor que existe en la cacheacute que puede ser bien distinta al real puesto que un posible perifeacuterico puede haber modificado su valor

El Modificador static

Dependiendo del entorno donde se declare la variable que la modifiquemos como static puede significar dos cosas muy distintas

1 Si declaramos una variable static dentro del cuerpo de una funcioacuten lo que estamos indicaacutendole al compilador es que dicha variable sea inicializada solo una vez (la primera vez que se llama a la funcioacuten) y el resto de veces que se llame a la funcioacuten la variable contendraacute el uacuteltimo valor asignado Esta variable soacutelo podraacute ser visible desde la funcioacuten que declara dicha variable Por ejemplo

void mifuncion() static int i=0 coutltltEn la entrada i vale ltltiltltendl

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 45:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

1 Si declaramos una variable static fuera del cuerpo de una funcioacuten lo que le estamos indicando al compilador es que dicha variable es privada para el modulo donde se implementa el coacutedigo del contexto de la variable es decir que otro fichero objeto binario no podraacute tener acceso a dicha variable utilizando el modificador extern Ejemplo

import pruebah variable privada para pruebacppstatic int i=0 void mifuncion() coutltltEn la entrada i vale ltltiltltendl for(int j=0jlt10j++) i++ coutltltEn la salida i vale ltltiltltendl

Tenga en cuenta que para este uacuteltimo caso usted podraacute acceder a la variable y desde cualquier funcioacuten que defina dentro de pruebacpp pero no tendraacute acceso desde cualquier fichero objeto o fuente que no sea pruebacpp

Espacio que ocupan la variables (en maacutequinas x86)

El espacio en bits que ocupan en la computadora una variable de este tipo se puede ver en la siguiente tabla

Tipo Nuacutemero de Bits

char 8

short 16

int 32

long int 64

float 32

double 64

Rango de los Tipos Primitivos

El rango que puede almacenar los tipos primitivos en C++ es muy importante para poder saber cual es el rango de valores que puede almacenar un tipo es necesario conocer el nuacutemero de bits del tipo El caso para enteros y para flotantes es distinto Para enteros se debe saber si el tipo es con signo o sin signo si es sin signo el rango de valores que puede almacenar es el siguiente

Si el tipo es con signo el rango es el siguiente

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 46:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Para ilustrar lo anterior supongamos que tenemos un entero de 16 bits sin signo entonces el rango de valores que puede almacenar es el siguiente

Para obtener el rango de un entero de 32 bits con signo se puede realizar el siguiente calculo

El caso de los nuacutemeros flotantes es distinto y depende en gran manera del compilador y el procesador que este utilizando Sin embargo hoy en diacutea la mayoriacutea de los compiladores y los procesadores utilizan en estaacutendar de la IEEE para representacioacuten en coma flotante Para saber mas al respecto ver IEEE floating-point standard

Tipos enumerados (enum)

Los tipos enumerados son un mecanismo usado en C y C++ con el objetivo de agrupar de alguna manera constantes simboacutelicas Para definir tipos enumerados se usa la palabra reservada enum

Ejemplo 1

enum dias domingo lunes martes miercoles jueves viernes sabado

En el ejemplo anterior se define por medio de enum el tipo enumerado dias en el mismo ejemplo se debe observar que dentro de la construccioacuten se definen las constantes simboacutelicas domingo lunes sabado y que a las mismas el compilador les asignaraacute respectivamente y por defecto los valores 0 1 2 3 4 5 6 Es decir las constantes mencionadas pueden usarse dentro del programa y este sabraacute a que valor hace referencia cada una de las mismas Por ejemplo la instruccioacuten cout ltlt domingo desplegaraacute 0 en la pantalla El siguiente ejemplo muestra como usar las constantes enumeradas en un ciclo for

for (int d = domingo d lt= sabado d++) cout ltlt d

En el siguiente ejemplo se define por medio de enum el tipo enumerado colores en el mismo se debe de observar la elinacioacuten del comportamiento por defecto ya que a la primera constante (gris) se le asigna en forma especiacutefica el valor de 7 de tal manera que la siguiente constante (grisoscuro) tendraacute un valor igual a 8 y la constante amarillo seraacute igual a 14

Ejemplo 2

enum colores gris = 7 grisoscuro amarillo = 14

Tipos definidos por el usuario

En muchas ocasiones descubriremos que los tipos primitivos no bastan para llevar a cabo ciertas tareas debido a esto el lenguaje C C++ da el soporte necesario para que el programador defina sus propios tipos Para definir tipos se usa la palabra reservada typedef Por ejemplo si deseamos definir un tipo de dato llamado entero podemos usar la sintaxis

typedef int entero

Luego podremos declarar variables constantes y funciones del tipo entero Por ejemplo

entero edad = 33

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 47:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

Un uso maacutes uacutetil y comuacuten es el empleo de typedef para definir datos estructurados Por ejemplo supongamos que deseamos definir un tipo estructurado llamado persona y que contenga nombre edad y sexo Entonces podemos definir persona como

typedef struct persona char nombre[32] int edad char sexo

Una vez que un tipo ya se ha definido el mismo puede emplearse para declarar variables y constantes de este Por ejemplo con la instruccioacuten

persona hombre

se estaacute declarando la variable hombre del tipo persona Luego para acceder a cada elemento de la variable hombre usaremos un mecanismo conocido como direccionamiento directo por medio del caracter de punto ( ) Por ejemplo la edad de hombre se debe indicar como

hombreedad

Variables y constantes

Una variable como su nombre lo indica es un determinado objeto cuyo valor puede cambiar durante el proceso de una tarea especiacutefica Contrario a una variable una constante es un determinado objeto cuyo valor no puede ser alterado durante el proceso de una tarea especiacutefica En C C++ para declarar variables no existe una palabra especial es decir las variables se declaraacuten escribiendo el tipo seguido de uno o maacutes identificadores o nombres de variables Por otro lado para declarar constantes existe la palabra reservada const asiacute como la directiva define A continuacioacuten se muestran ejemplos de declaracioacuten de variables y constantes

Variables Constantes Constantes

int a const int a = 100 define a 100

float b const float b = 100 define b 100

Notas

A diferencia de las constantes declaradas con la palabra const los siacutembolos definidos con define no ocupan espacio en la memoria del coacutedigo ejecutable resultante

El tipo de la variable o constante puede ser cualquiera de los listados en Tipos primitivos o bien de un tipo definido por el usuario

Las constantes son usadas a menudo con un doble propoacutesito el primero es con el fin de hacer maacutes legible el coacutedigo del programa es decir si se tiene (por ejemplo) la constante numerica 31416 y esta representa al nuacutemero pi entonces podemos hacer declaraciones tales como

define pi 31416

En este caso podremos usar la palabra pi en cualquier parte delprograma y el compilador se encargaraacute de cambiar dicho simbolo por 31416

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes
Page 48:  · Web viewEs un área muy importante manejada directamente por la UCP para alojar datos durante la ejecución del programa. Su nombre deriva de su propio mecanismo de funcionamiento

o bien

const pi = 31416

En este otro caso podremos usar la palabra pi en cualquier parte del programa y el compilador se encargaraacute de cambiar dicho siacutembolo

por una referencia a la constante pi guardada en la memoria

  • 11 Introduccioacuten a la POO
    • sect1 Queacute es eso de los Objetos
    • sect2 Resumen
      • 12 El lenguaje C++
        • sect1 Generalidades
        • sect2 Consejos para mejorar el rendimiento
        • 121 Leacutexico y conceptos fundamentales
          • sect1 Presentacioacuten
          • sect2 Algunos conceptos
              • 13 Estructura de un programa
                • sect1 Sinopsis
                • 131a Sentencias
                  • sect1 Introduccioacuten
                  • sect2 Sintaxis de las sentencias C++
                    • 132 Almacenamiento
                      • sect1 Preaacutembulo
                      • sect2 El proceso de carga
                      • sect3 Segmento de coacutedigo
                      • sect4 Segmento de datos
                      • sect41 Datos estaacuteticos
                      • sect41a Datos estaacuteticos inicializados
                      • sect41b Datos estaacuteticos no inicializados
                      • sect42 Pila (Stack)
                      • sect43 Montoacuten local (Local heap)
                      • sect431 Inconvenientes del montoacuten
                          • 14 Proceso de creacioacuten de un programa
                            • sect1 Sinopsis
                            • sect2 Presentacioacuten del problema
                            • sect3 Comprender el problema
                            • sect4 Disentildear los ficheros y moacutedulos
                            • sect5 Escribir el coacutedigo
                            • sect6 Preproceso
                            • sect7 Anaacutelisis sintaacutectico
                            • sect8 Anaacutelisis semaacutentico
                            • sect9 Generador de coacutedigo
                            • sect10 Enlazado
                            • sect101 Versioacuten de depuracioacuten
                            • sect102 Versioacuten de publicacioacuten
                            • sect103 Libreriacutea
                            • sect111 Tipos de errores
                            • sect112 Gravedad de los errores
                            • sect113 Generalidades sobre los errores de compilacioacuten
                            • sect114 Errores de ejecucioacuten
                            • sect12 Recursos
                            • 142 Compilacioacuten
                              • sect1 Sinopsis
                              • sect2 Unidad de compilacioacuten
                              • sect3 Deformacioacuten de nombres
                              • sect31 Evitar el planchado de nombres
                                  • Proceso de desarrollo de un programa
                                    • Comentarios
                                    • Utilizacioacuten de la consola o terminal
                                      • Sintaxis
                                        • El punto y coma
                                        • Separador de bloque
                                        • Espacios y tabuladores
                                          • Tipos primitivos
                                            • El modificador long
                                            • El Modificador short
                                            • El Modificador unsigned
                                            • El Modificador register
                                            • El Modificador volatile
                                            • El Modificador static
                                            • Espacio que ocupan la variables (en maacutequinas x86)
                                              • Rango de los Tipos Primitivos
                                                  • Tipos enumerados (enum)
                                                  • Tipos definidos por el usuario
                                                  • Variables y constantes