Beruflich Dokumente
Kultur Dokumente
http://www.zator.com/Cpp/E_Cr.htm Prlogo o o o o o o o o o o o o o o o o o o o o o o o o o o o o o Resumen de Contenido (esta pgina) ndice Convenciones y notacin 0.1 El Ordenador Electrnico Digital 0.2 El Sistema Operativo 0.3 El Hardware 1.1 Introduccin a la POO 1.2 El lenguaje C++ 1.3 Estructura de un programa 1.4 Proceso de creacin de un programa 1.5 Secuencia de ejecucin 1.6 Tratamiento de excepciones 1.7 Programacin actual 1.8 Estructura de la informacin 2.1 Atributos 2.2 Tipos de datos 3.1 Comentarios 3.2 Tokens 4.1 Declaraciones 4.2 Punteros 4.3 Matrices 4.4 Funciones 4.5 Estructuras 4.6 Campos de bits 4.7 Uniones 4.8 Enumeraciones 4.9 Operadores 4.10 Sentencias 4.11 Clases
0 Introduccin
1 Programacin C++
2 Variables
3 Elementos lxicos
o o o o o o o
4.12 Plantillas 4.13 Tecnicismos 5.1 STL 5.2 Internacionalizacin 5.3 Entradas/salidas 5.5 Librera clsica 6.1 Reglas de lectura
5. Librera Estndar
A modo de prlogo
"... Creo que sera tan extravagante actuar decentemente en poltica que podra llegar a ser rentable. Y si no lo fuera, al menos nos respetaramos a nosotros mismos. Que no es poco". Antonio Robles en "Ciudadanos de Catalua y VidalQuadras" [7]. Artculo aparecido en el peridico on-line Libertad Digital
Todo esto puedes saltrtelo, se trata solo de justificarme a m mismo... Ms que "curso", tal vez deberamos decir apuntes, chuleta, traduccin o chapuza (para los ms exigentes). En principio son, mejor debera decir "nacieron", simplemente como unos apuntes personales para ponerme al da; para refrescar los conocimientos sobre C/C++, que tena bastante oxidados, pues los nicos pinitos al respecto que haba en mi "Currculum" fueron lo sucinto para hacer un pequesimo programa que leyera y escribiera en determinadas posiciones de memoria en un PC bajo MS-DOS; se trataba entonces de controlar una tarjeta de adquisicin analgico-digital especfica. La herramienta fue el compilador C 5.1 de Microsoft que an conservo. Ahora, unos 15 aos ms tarde, me veo en la necesidad de volver a utilizar el C; mientras tanto he odo, ledo y utilizado algo la programacin orientada a objetos, de forma que me pareca lo natural hacerlo en C++, as que lanza en ristre como D. Quijote, descargo el magnfico compilador C++ Builder de Borland-Imprise (que es gratis total), saco los viejos libros de C, y sobre todo, me bajo todas las ayudas que hay sobre el tema en el "site" de Borland. Adems, aunque conservo un librito de un tal Bjarne Stroustrup: "The C++ programming language", que vena de regalo con un compilador que compr entonces (1989): "Zortech C++ Compiler" (con el que confieso que no llegu a hacer gran cosa) y del que ahora me entero que el tal Stroustrup, adems de tener un nombre impronunciable, es nada menos que el inventor del C++. Bueno, a lo que iba: me pareca que el librito era poca cosa, as que encargo el nuevo y actualizado; un "tocho" de ms de mil pginas, que cuesta un @ y que es el no va ms sobre el tema [1]. Adems descargo algunas cosas que encuentro por ah sobre C++ que me parecen interesantes, algunas de las cuales encontrareis en el captulo de bibliografa (perdn si se me olvida citar alguna).
La primera sorpresa que me encuentro, al empezar a hincarle el diente a todo mi flamante bagaje informativo, es que aunque el viejo C de K&R [3] sigue estando bajo la piel del nuevo C++, el lenguaje ha evolucionado. Hace poco, mi hermano que es precisamente profesor de informtica, me dijo que el C era un lenguaje muy pequeo y fcil "Ni siguiera las E/S forman parte de l"; puede que eso sea verdad, creo que s [4]. Pero de lo que no me cabe duda, es que pertenezcan o no las rutinas de E/S al propio lenguaje (al fin y al cabo, salvo que hagamos un programa "autista", tendremos que utilizarlas), el pequeo beb ha crecido hasta convertirse en el monstruo que es ahora. Miro los ejemplos y ni siquiera entiendo la notacin... Lo que pensaba que sera un paseo militar, empieza a convertirse en algo a lo que tengo que dedicar muchas (muchsimas) horas, as que decido pasar muy despacito desde el principio hasta el final, y no se me ocurre mejor manera que ir haciendo mi propio libro de C++ por el sistema de ir cortando, pegando y traduciendo los diversos captulos del manual de ayuda "C++ Builder Languaje Guide" [2]. En algunos puntos voy incluyendo mis propias explicaciones o entresacados de otros textos que me parecen reveladores. Adems de enterarme, lo que pretendo es llegar a tener un texto donde yo mismo pueda encontrar lo que quiero sin que ocurra lo de siempre: "Lo he ledo en algn sitio pero no recuerdo donde...", con todos los ndices, tablas y referencias cruzadas que estime convenientes; como veris estoy describiendo mi propio mtodo de estudio cuando algo me interesa. El siguiente paso es bastante obvio: Porqu no ponerlo en la Red por si puede servirle a alguien ms?. Ya se que en la red hay mucho y bueno, pero casi todo en ingls; adems, pienso que si algn estudiante o programador hispano-hablante saca de aqu, aunque solo sea una idea o un concepto, habr cumplido su cometido. Dicho todo esto, solo me queda volver a advertiros que no se trata del docto trabajo de un sper experto en el tema. Se trata simplemente del trabajo de un programador "patatero" (que ha pelado muchsimas patatas) [5]. Si hay algn error es porque yo mismo no lo tengo claro, y por supuesto os agradecera cualquier puntualizacin, crtica o aportacin al respecto. Entiendo que a ms de uno le parezca un atrevimiento hacer unos apuntes, traduccin, etc sobre C++ admitiendo el propio desconocimiento; lleva razn, es atrevido, por eso he intentado explicaros el origen y la intencin. Adems, a fin de cuentas se ven por ah cosas peores; conozco a uno que ha puesto en su pgina personal el "careto" de su perro... Nada ms. Que sea leve!. Antes de despedirme, solo contaros un pequeo chiste que circula por las escuelas de informtica. Viene a decir que Stroustrup se mostr muy extraado del xito de su C++, y que en "petit comit" haba reconocido que lo nico que pretendi era que le subieran el sueldo a los programadores de los laboratorios de AT&T, y que lamentaba que algunas empresas hubieran ido a la bancarrota intentando pasar sus programas a C++...[6] Greetings (que dicen los Yanquis) Adolfo J. Milln Comienzo: Cdiz (Espaa), Agosto 2.000 Inicio.
[1] Casi todo el mundo est de acuerdo en que no es un libro para estudiar C++, sino la suprema referencia, "La Biblia" del C++, y que para entenderlo es imprescindible haber estudiado C++ previamente ("To read this book, you will need tons of C++ & OOP knowledge, even if you are an ace C programmer"). Ms datos sobre este libro en la Bibliografa ( comentarios sobre el mismo en Amazon ( www.amazon.com). Stroustrp 2000), extensos
[2] As pues, los derechos de autor corresponden principalmente a Borland-Imprise, pues originalmente se trata de una traduccin "No autorizada" de dicho manual. Espero que no me demanden por ello; el resto del copyright y los errores son mos. [3] K&R. Siglas con que se conoce a Brian W. Kernighan y Dennis M. Ritchie, creadores del lenguaje C. [4] Kernighan y Ritchie parece que tambin estn de acuerdo: "El lenguaje C no es grande y no le est bien un gran libro".... "Puesto que C es relativamente pequeo, se puede describir en un pequeo espacio y aprender con rapidez. En verdad, un programador puede razonablemente esperar conocer, entender y utilizar la totalidad del lenguaje" ( [5] Bueno... tambin tengo mi culturilla universitaria. [6] Mucho tiempo despus de escribir este prlogo, un amable lector me envi un divertidsimo email con una versin apcrifa del chiste aludido. Est en forma de una supuesta entrevista con Stroustrup, en la que este explica las razones de la invencin del lenguaje. Incluyo su trascripcin literal ( 0.Pw1) para que el lector tenga una idea aproximada de lo que le espera :-)) K&R).
[7] S. Ya se que no tiene nada que ver con el C++ o con la Informtica, as que perdonadme. Es que acabo de leerlo y me ha parecido tan hermoso que no he podido resistir la tentacin de ponerlo en algn sitio (que no solo de pan vive El Hombre!!).
1 Convenciones y notacin
Las notas a pi de pgina se han sealado con numeracin arbiga entre corchetes con un hipervnculo al lugar de la cita [1]. Las palabras clave y los identificadores que tienen un sentido especfico en C++, se han sealado en negrita y color negro. Por ejemplo: "auto, extern y register no son permitidos, s en cambio
static"
Cuando queremos destacar alguna palabra, smbolo o frase, utilizamos cuatro sistemas: resaltar el fondo; en negrita color azul, o simplemente en color rojo. Cuando queremos resaltar una idea (prrafo) utilizamos una lmpara .
Para los textos de ejemplos y explicaciones, tal como se escribiran en el cdigo fuente, se ha utilizado el tipo courier de espacio fijo con un fondo distinto y un sangrado a la izquierda Cuando va dentro de una frase de texto normal como aqu, adems del cambio de tipo y el fondo, se ha utilizado un color negro para resaltar la diferencia.
2 Referencias
A lo largo del texto existen innumerables referencias a otros epgrafes, con sus correspondientes hipervnculos, donde se comenta un concepto relacionado. El hipervnculo est entre parntesis con un pequeo icono ( o ). Por ejemplo: "La coma se usa tambin como un operador en las expresiones con coma ( 4.10.5)". En estos casos, y indican que se trata de una referencia en esta misma publicacin. Cuando el asunto referenciado est en una posicin anterior o posterior de la misma pgina, se utilizan los iconos y respectivamente. y hacen subir
y bajar en la misma pgina. El smbolo conduce a la pgina correspondiente, mientras que indica que se abrir una ventana auxiliar mostrando el asunto sealado. En estos casos se trata de una nota o ejemplo complementario al contenido de la pgina actual. Cuando la referencia se refiere a un libro tradicional (en papel), como los citados en la bibliografa, el icono utilizado es un libro abierto: . Cuando se trata de un artculo, libro o publicacin disponible .
Finalmente, cuando la referencia se refiere a un artculo de revista o publicacin peridica tradicional, el icono es un montn de hojas . Este recurso se ha intentado utilizar al mnimo, para evitar al lector la frustracin de tener una referencia quizs inaccesible.
Ejemplo:
Una secuencia de declaraciones de propiedades de cualquier tipo (por ejemplo int capacidad;), incluyendo enumeraciones, campos de bits etc; as como declaracin y definicin de mtodos. Todos ellos con especificadores opcionales de acceso y de tipo de almacenamiento (auto, extern y
4.11.7). Los elementos as definidos se denominan miembros de la clase; hemos dicho que son de dos tipo: propiedades de clase y mtodos de clase. Ejemplo: class vuelo { char nombre[30]; int capacidad; public: // // // // vuelo es la clase por defecto es privado capacidad es una propiedad a partir de aqu todo es pblico
// despegue es un mtodo
[1] Esto es una nota a pi de pgina. Si en ocasiones ves aparecer en el texto la nota [2] antes que la [1] no te preocupes; es que he tenido que incluir la segunda nota en una posicin anterior a la [1] que ya estaba colocada. De momento no he descubierto un sistema cmodo para renumerarlas al estilo de los procesadores de texto (FrontPage no tiene todava esta opcin).
Introduccin al C++
... appalled at the monstrous messes that computer scientists can produce under the name of improvements. It is to efforts such as C++ that I here refer. These artefacts are filled with frills and features but lack coherence, simplicity, understandability and implementability. If computer scientists could see that art is at the root of the best science, such ugly creatures could never take birth. R.P.Mody "C in Education and Software Engineering", ACM SIGCSE Bulletin Vol.23 No. 3 September 1991.
Algol68 ( Stroustrup 1987), para lo bueno y para lo malo [1], el lenguaje C++ incorpora muchas caractersticas heredadas del C, su ancestro ms directo, el cual recoge a su vez influencias anteriores: B, BCPL ( 0.Iw2), etc. ( K&R).
Nota: es mucho lo que puede encontrarse en la red sobre los orgenes del C y sus influencias previas, pero uno de los mejores documentos, con la autoridad que le confiere ser precisamente de uno de sus creadores, es: "The development of the C language" ( Dennis M. Ritchie).
Para los que estudian C++ como una herramienta de trabajo, aunque en realidad su profesin no es la informtica, sino otra ms "cientfica", una advertencia: como todos los lenguajes de programacin (obra de los ltimos cinco segundos de la evolucin del hombre), C++ es muy "artificial", y aunque los informticos son gente bastante lgica, las cosas son as porque s. No se le puede pedir el tipo de lgica que encontramos en las Matemticas o en la Fsica por ejemplo. El resultado de todo esto es que C++ est repleto de conceptos y detalles inter-relacionados; reglas que son as por "definicin"; porque a su inventor le pareci que eran la mejor forma de hacerlas o porque vienen heredadas [3]. Cuestiones que podran quizs ser de otro modo, pero son as por
compatibilidad (con el C); otras reglas tienen sus excepciones tambin por tradicin o por herencia; etc. Para el comn de los mortales es imposible hacerse una idea exacta con una primera lectura, pues muchos conceptos solo cobran su verdadera dimensin cuando se entienden otros a los que no se ha llegado todava [1a]. Hace tiempo le sobre un personaje histrico del que decan que tena tal capacidad, que lea los libros por el sistema de ir arrancando y tirando las pginas ledas. Desde luego no es el caso del C+ +; es ms que posible que cualquier libro de C++ requiera mltiples relecturas, cada una de las cuales nos proporcionar una mejor y ms detallada perspectiva del lenguaje, de sus enormes posibilidades e incluso de los niveles de refinamiento y sofisticacin que pueden alcanzarse con l [2]. El propio inventor del lenguaje afirma al respecto: "Don't panic!. All will become clear in time" [2a]. Se me ocurre que una buena analoga seran esas imgenes Web que aparecen progresivamente y que solo se ven con nitidez cuando se ha terminado su descarga [4]. Las referencias a otros puntos hace que constantemente tengamos que saltar de un sitio a otro (por fortuna los documentos HTML y el navegador vienen que ni pintados para el caso, podemos saltar a una cita y volver inmediatamente el punto de partida con un par de clic de ratn). Est fuera de toda duda que C++ es un lenguaje difcil y spero; podramos citar al menos una decena de "lindezas" que se han dicho acerca de l (hemos incluido aqu alguna con objeto de que el estudiante sepa a que se enfrenta). Sin embargo, nuestro nimo no es disuasorio sino todo lo contrario; considere que simplemente debe dedicarle una especial atencin y esfuerzo, en la seguridad de que el lenguaje lo merece. Tengo un amigo al que le gusta decir que hay dos clases de "informticos": Los que saben C++ y los que no merecen llamarse informticos. Seguramente es exagerado, pero estoy convencido que su estudio constituye la base de la informtica actual. Su rastro puede verse por doquier, incluso en lenguajes tan de moda y actuales como Java, php o JavaScript. De forma que su conocimiento le da al estudiante no ocasional de informtica una inmejorable posicin de partida para adentrarse en otras materias. En mi opinin el estudio de C++ en las Escuelas de Informtica sera comparable al estudio de anatoma en las de Medicina. Seguramente necesitar bastantes horas para llegar a dominar C++, pero es con diferencia "El Rey" de los lenguajes de programacin. Habr merecido la pena!.
compiladores distintos aplicados al mismo cdigo conduzcan a resultados diferentes. Por supuesto, no nos referimos a que 2 + 2 dejen de ser 4, sino a errores y avisos de cosas que son o no permitidas en segn qu plataforma. A las consideraciones anteriores hay que aadir que los ordenadores son finitos, lo que exige que las aplicaciones que corren en ellos sean necesariamente finitas. En consecuencia, los fabricantes de compiladores se ven obligados a imponer ciertas condiciones y lmites a sus productos. Por ejemplo: el Estndar dice que los bloques, zonas de programa englobadas en llaves { }, pueden ser anidados (bloques dentro de otros bloques). Sin embargo las implementaciones pueden sealar un lmite mximo de anidamiento para estos casos. Naturalmente los lmites y condiciones pueden variar para cada compilador. El Estndar solo exige que estas limitaciones estn debidamente documentadas. Nota: En esta obra hemos utilizado los tres compiladores C++ de uso ms popular en el mundo de la informtica personal y empresarial: El compilador Borland C++ de Imprise. El Visual C++ de Microsoft, y el C++ de la Open Software Foundation (GNU Cpp). Los dos primeros son para la plataforma Wintel. El ltimo para Linux. Desafortunadamente, la versin que dispongo de "Visual" es bastante antigua (1998). Como comprobar el lector a lo largo de estas pginas, aunque por fortuna los tres compiladores son bastante consistentes y se aproximan al Estndar, esta concordancia no siempre es perfecta y los resultados no siempre coinciden en algunos rincones del lenguaje. En aquellas ocasiones en que hemos detectado disparidades se han incluido las observaciones pertinentes. Tenga en cuenta que estas se refieren siempre a versiones concretas de cada compilador y que las divergencias pueden o no manifestarse si se utilizan otros compiladores u otras versiones.
Tanto si se va a acometer un nuevo proyecto, como si se debe mantener el cdigo de aplicaciones ya existentes (que los anglosajones denominan "legacy code"), es importante tener claras algunas cuestiones relativas a la estandarizacin de lenguaje y al grado de adaptacin de cada plataforma o compilador concreto. Estas cuestiones aparecen con cierta regularidad en los foros de debate, y aunque no conciernen estrictamente a nefito, en cambio s son importantes para el profesional que se enfrenta a situaciones del mundo real. Son las siguientes:
hasta las modernas, en las que es del orden del 99%. De acuerdo con los expertos, los compiladores ms conformes por el momento son: la serie GNU c++ 4*; VC 2k3; VC 2k5; Intel C++ 8.0 y Comeau 4.2 (o versiones posteriores). Salvo casos de fuerza mayor, que se deba lidiar con "legacy code", el consejo de los expertos es no considerar siquiera cualquier compilador cuyo fabricante no lo haya actualizado en los ltimos cuatro aos.
Si eres de los que prefieren tener la idea de un cierto orden, te aconsejo que utilices el ndice; est a una distancia de un solo clic de ratn de cualquier pgina en que te encuentres: [Indice] en la esquina superior derecha. Inicio. [1] Respecto a esta influencia, hay opiniones para todos los gustos. En el enlace adjunto puede encontrar una de ellas, "Why C++ Sucks" (en ingls). Originalmente el documento estaba en http://world.std.com/, sin embargo, a mediados de 2006 un lector me avis que el enlace estaba roto. No he podido volver a encontrar el documento original (parece como si se lo hubiese tragado la red). Sin embargo, afortunadamente conservo una copia en mi archivo histrico Why C++ Sucks.
[1a] "Then there are the many hidden features in C++ that you cannot reveal up front"... "There is a lot to learn after you learn the language. First you solo. Then you get your pilot's license. Then you learn how to fly. Learning C++ is a process of discovery". Al Stevens "C. Programming". Dr. Dobb's Journal. Sept. 1992. [2] Es frecuente que encontremos trozos de cdigo elegantsimos pero tambin difciles de desentraar en una primera lectura. Como botn de muestra, las dos sentencias que siguen son perfectamente correctas en c++: int z = *pt3+-*++pt3; void (_USERENTRY * _RTLENTRY _EXPFUNC32 signal(int __sig, void (_USERENTRY * __func)(int))) (int); [2a] Stroustrup TC++PL 2.9 [1]
[3] Los comits de estandarizacin tambin tienen mucho que decir al respecto, de forma que la versin "Estndar" de cualquier lenguaje es algo que se escapa de las manos y del control de su creador inicial. [4] Son las imgenes GIF entrelazadas o las JPEG progresivas. [5] "Not proprietary" que no son propiedad intelectual de ninguna empresa o institucin. De esta forma no existe un nico "fabricante" del lenguaje que decide sus caractersticas. En caso contrario, por ejemplo el de Java, propiedad de la compaa SUN, es esta ltima la que controla su desarrollo. [6] Desde su alumbramiento, el Dr. Stroustrup ha seguido muy de cerca la evolucin y desarrollo de su "criatura", aunque desde luego, actualmente la ltima palabra la tiene el comit encargado de elaborar el Estndar al que l mismo pertenece.
realidad las dos caras de una misma moneda". Martin Davis "La Computadora Universal, de Leibniz a Turing". Editorial Debate S.A. Madrid 2002.
1 Presentacin:
Imaginamos sobradamente conocidos por cualquier estudiante de C++ los principios generales sobre los que se basan los ordenadores electrnicos digitales; las mquinas en las que probablemente se ejecutarn sus programas. Sin embargo, no est de ms un brevsimo repaso a fin de refrescar y traer al tiempo presente algunos conceptos. Nota: En muchos pases hispano-hablantes de cultura tcnica ms influenciada por USA, se utiliza el trmino "computadora" por ordenador; ms parecida a su equivalente ingls "Computer". Por su parte, la versin castellana deriva del francs "Ordinateur". Esta es tambin la razn por la que en hispano Amrica se dice "La PC", mientras que por aqu decimos "El PC", en referencia al ordenador (masculino).
as, que el universo de las computadoras electrnicas digitales es un ocano de nmeros binarios que representan datos e instrucciones para su manipulacin. Nota: No confundir los conceptos: electrnico (basados en la electrnica); digital (utilizar magnitudes discretas representadas por nmeros) y binarios (utilizar este modo de representacin, una lgica y un lgebra de Boole Int Ap.K). Nada impide la existencia de ordenadores no electrnicos. Por ejemplo, mecnicos, pticos, biolgicos o basados en fluidos. Tambin han existido y existen ordenadores analgicos (no digitales) exclusivamente mecnicos. Por ejemplo, la humilde regla de clculo, o dispositivos ms sofisticados, como elementos de puntera y direccin de tiro de artillera. Tampoco existe inconveniente terico para la existencia de ordenadores digitales no binarios [9]. El hecho de que los actuales ordenadores electrnicos digitales sean binarios, se debe, entre otras razones, a que los circuitos elctricos estn especialmente adaptados al modo binario. Simplemente haciendo corresponder los dos posibles valores de la variable con dos estados fsicos de un circuito o dispositivo. Por ejemplo, con los estados de: conduccin no conduccin; tensin, sin tensin; magnetizado no magnetizado; con luz, sin luz; Etc. Como el lgebra de Boole [1] maneja variables que solo pueden tener dos estados ("cierto" y "falso"), es muy fcil representar y emular comportamientos y ecuaciones de este lgebra mediante circuitos electrnicos. As, construir un circuito electrnico que responda (que proporcione como salida) el OR, AND, NOR, XNOR, Etc. de ciertas variables de "entrada", es trivial desde el punto de vista de diseo de circuitos lgicos. Es relativamente fcil disear un circuito digital que responda a unas "Ecuaciones" lgicas (de Boole) por complejas que sean. Nota: Han existido intentos de construir ordenadores digitales en base a lgicas no binarias. Por ejemplo, "ternarias". Actualmente se empieza a hablar de la computacin cuntica, basada en algo distinto a dos estados mutuamente exclusivos.
Nota: En algunos Sistemas, por ejemplo Windows, es costumbre que los ficheros del mismo tipo (de la misma "familia") tengan nombres con la misma terminacin [10]. Tradicionalmente esta terminacin la componen tres letras despus del nombre separadas de l por un punto, lo que permite identificar fcilmente los ficheros de la misma familia. Existen tantos tipos como la imaginacin de los programadores y fabricantes de software han sido capaces de crear (.TXT; .DLL; .DOC; .ASP; Etc.) Generalmente el sistema operativo asocia cada fichero (no ejecutable) con una aplicacin (ejecutable) que es la encargada de su manejo [8]. A este proceso se le denomina asignacin de extensiones de nombres de archivo.
short. De los segundos existe menos variedad; bsicamente solo dos tipos: caracteres estrechos y anchos (char y wchar_t). En cambio presentan la ventaja de que pueden
agruparse en cadenas (arrays o matrices) de cualquier longitud. Son las denominadas "cadenas alfanumricas", en las que sus elementos (caracteres) pueden ser alfabticos (letras), numricos (guarismos) y signos de puntuacin (interrogacin, punto, coma, Etc.) Ambos tipos de datos, numricos y caracteres, son conocidos colectivamente como escalares. En ellos pueden distinguirse varios aspectos:
bits ( 2.2.1a). La internacionalizacin de la informtica, que empez a manejar juegos de caracteres de otras culturas e idiomas distintos del ingls-americano, oblig a utilizar tablas ms extensas, en las que rpidamente se sobrepas la cantidad de 256 elementos (caracteres distintos), que es el mximo que puede expresarse con 8 bits (ver ms adelante ).
Adems de la anterior, razones de precisin, y de poder representar cantidades positivas y negativas, ha motivado la aparicin de algunas variedades de representacin (binarias desde luego) a cuyos detalles dedicamos un captulo ( 2.2.4a).
Nota: Aunque hayamos sealado que existen sistemas de codificacin de ancho variable para los caracteres, como veremos a continuacin, la representacin interna de estos utiliza siempre un formato de ancho fijo, dejando la representacin de ancho variable para almacenamientos externos y comunicaciones.
Observe la diferencia entre los diversos conceptos involucrados: El nmero o cantidad "mil setecientos noventa y ocho", su representacin en el sistema decimal (1978) y las "cifras" o "guarismos" que componen su representacin en este "sistema de numeracin" (en este caso cuatro cifras: 1, 7, 8 y 9 colocadas en un cierto orden). Desde la escuela primaria sabemos que este en este sistema, el valor de las cifras viene complementado por su posicin en el conjunto (decimos que es posicional), de forma que el valor total de una expresin viene representado por el producto de su valor-base (0 a 9) multiplicado por la potencia de 10 que corresponda segn su posicin. Al final se suman los resultados parciales. Resulta as que en el sistema decimal, la cantidad mas alta que se puede representar mediante una cantidad de cuatro cifras, nnnn es, como mximo: 9 x 103 + 9 x 102 + 9 x 101 + 9 x 100 == 9999 (10.000 si le aadimos el cero).
Es fcil verificar que un nmero decimal de n dgitos puede representar como mximo una cantidad igual a 10n. En el caso del ejemplo, para 4 dgitos, 104 = 10000. Observe que el mismo concepto (la misma cantidad) puede ser representada utilizando distintos sistemas de numeracin, por ejemplo: MDCCXCVIII en nmeros romanos (como dijimos, un sistema muy poco adecuado para las matemticas).
apagado es (puede ser) un almacenamiento de 1 bit de informacin (basta con hacer corresponder "encendido" con uno de los valores y "apagado" con el otro). El asunto es que estas variables "binarias" (que solo pueden adoptar dos valores distintos), son mucho mas adecuadas para su representacin en dispositivos elctricos, magnticos y pticos que las "decimales", por lo que es este el "formato" elegido para la representacin y almacenamiento de datos numricos en los ordenadores electrnicos digitales. La capacidad de representacin de este sistema es sin embargo menor que en el decimal, as, una cantidad binaria de 4 dgitos puede representar como mximo: 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 == 15 (16 si aadimos el cero)
Es fcil verificar que, en este sistema de numeracin, un nmero de n dgitos puede representar como mximo una cantidad igual a 2n (en el caso del ejemplo, para 4 dgitos, 24 = 16). La tabla adjunta expresa las cantidades que se obtienen con la unidad, seguida de cierto nmero n de ceros en los sistemas decimal y binario. Lo que representa las potencias n de la base de numeracin. Es decir: 10n o 2n. Base 10 Nmero decimal Base 2 Nmero binario 100 101 102 103 104 105 106 107 108 109 1010 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000 20 21 22 23 24 25 26 27 28 29 210 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000 Equivalente decimal 1 2 4 8 16 32 64 128 256 512 1024
informtica a excepcin de algunos supuestos tericos. Por ejemplo, en la mquina de Turing ( 0.1.1).
5 Almacenamiento interno
Tradicionalmente el almacenamiento interno de los ordenadores se organiza desde el punto de vista lgico en grupos de 8 (o mltiplos de 8) cifras binarias (bits). Estos conjuntos (octetos) son la menor cantidad de informacin que trata el ordenador con entidad propia; reciben el nombre de bytes y suele abreviarse con B. Por ejemplo, 16 Kb y 16 KB. Se refieren a 16000 bits y 128.000 bits respectivamente [4]. Nota: Hemos sealado que bit es abreviatura de Binary Digit, mientras que el nombre Byte fue acuado en la dcada de los 50 por Werner Bushholz de la IBM; la palabra proviene de una mutacin de "bit", hecha de forma que no hubiese confusin al pronunciarlas (bit y byte suenan muy distintas en ingls). En ocasiones, adems de los octetos, se utilizan agrupaciones de 4 bits, reciben el nombre de nibble. As que 2 nibbles == 1 Byte. Podemos usar un smil para entenderlo: aunque nuestro alfabeto tiene 26 caracteres no solemos utilizarlos aislados. Para que tengan significado se utilizan en grupos (palabras). Los ordenadores utilizan tambin palabras, solo que estas son siempre de la misma longitud (8, 16, 32 o 64 bits segn el modelo de procesador). Segn lo anterior, un octeto (una "palabra" de 8 bits), 1 Byte, puede contener un nmero de hasta 28 = 256, lo que deriva en que si reservamos una palabra de 8 bits para "describir" (contener) una variable, sabemos de antemano que dicha variable no va a poder adoptar ms de 256 estados distintos. Esto, unido al hecho de que la forma de representacin interna utiliza el sistema binario y los elementos y circuitos fsicos son igualmente binarios (pueden adoptar solo dos estados), hacen que las potencias de dos: 8, 16, 32, 64 Etc. sean "nmeros mgicos" en el mundo de las computadoras.
Alineacin interna (
4.6.1)
Inicio. [1] George Boole (1815-1864). Matemtico ingls cuyos trabajos tericos sobre conjuntos de nmeros binarios (que solo pueden adoptar dos valores), ayud a establecer las bases de la moderna lgica simblica. Su lgebra de la lgica binaria es tambin denominada lgebra Booleana. [2] Nos referimos a las lenguas o lenguajes "Naturales" en contraposicin a los "Artificiales" utilizados en informtica. Los primeros han sido inventados espontneamente por el hombre (a excepcin del Esperanto) y son el resultado de mutaciones que se pierden en la noche de los tiempos. Los segundos han sido y estn siendo inventados por los informticos para comunicarse con los ordenadores (computadoras). [3] Ya se est experimentando con olores. Creo que incluso existe alguna patente al respecto. [4] Por supuesto byte puede escribirse con mayscula y minscula, pero es costumbre informtica utilizar la mayscula -Byte-, mientras que bit siempre con minscula. En mis tiempos -cuando la gente denominaba a estos cacharros "cerebros" electrnicos- era pecado mortal no hacerlo as, de forma que ante una expresin xxx KB o yyy Kb todo el mundo saba a que atenerse. [5] Ahora que el asunto parece estar de moda, digamos que no solo debemos a la cultura Islmica las cifras numricas, incluso muchos textos clsicos han llegado hasta nosotros a travs del Islam. Tambin conocimientos de astronoma y medicina. [6] Existe un tercer grupo de ficheros, los ejecutables, que se correspondera con lo que hemos denominado algoritmos (instrucciones) y que podran considerarse dentro del grupo de los binarios. Adems de los citados, pueden existir otros tipos, como directorios y ficheros de dispositivo. Estos ltimos son artificios utilizados por el Sistema Operativo. Los ficheros de directorio sirven para organizar el contenido del disco en carpetas y subcarpetas. Los ficheros de dispositivo representan la interfaz de los perifricos controlados por el SO. [7] Lo contrario obligara a reservar para "todos" los datos numricos, el espacio correspondiente al mayor de ellos (mxima entidad numrica soportada por el programa). [8] A menudo es un problema conocer la naturaleza de los ficheros que encontramos en nuestro sistema. Cuando esto no es posible, puede intentarse, al menos, conocer el tipo o familia a que pertenece un fichero determinado por su terminacin. Entre los sitios que podran citarse, recomendar dos: Filext y File-Extensions Org. Ambos contienen una extensa base de datos y toneladas de informacin al respecto. [9] Incluso en publicaciones muy autorizadas, es frecuente ver como se confunden los trminos digital y binario, tomndolos como sinnimos cuando en realidad no lo son (los dgitos no tienen porqu ser binarios). Como hemos sealado, pueden existir ordenadores digitales de lgica ternaria o de ms estados. Por ejemplo, decimal. ENIAC, considerado como el primer ordenador digital electrnico de clculo numrico ( A2.1), tena una arquitectura decimal, de forma que la representacin interna de los nmeros no era binaria.
[10] Lo anterior no es cierto en UNIX, donde tradicionalmente los ficheros no tienen terminacin especfica. En cuanto a Microsoft, los sistemas de archivo de sus Sistemas Operativos no reconocen diferencias entre Maysculas/minsculas en los nombres de ficheros, de forma que la tcnica de utilizar una terminacin de tres caracteres para determinar el tipo de un fichero -lo que se conoce como TLA "Tree Letter Acronym"- tiene el problema de que solo permite 17.576 ATL nicos suponiendo las letras del alfabeto ingls americano.
El problema es que un sistema moderno como Windows es bastante complejo, y aunque es cierto que algunos lenguajes encapsulan los servicios del sistema mediante una capa de software aadido, que intenta enmascarar su complejidad, como dice Petzold ( complejidad saltar fuera y le morder la pierna". PW5E): "Antes o despus esta
El presente captulo incluye unas pinceladas generales sobre esta parte del software que controla el funcionamiento del ordenador, introduciendo algunos conceptos que son imprescindibles para entender otros relacionados con la multiprogramacin y multitarea, adems de ser fundamentales para entender como y porqu funcionan los programas C++ (o de cualquier otro lenguaje) en los entornos operativos actuales. Sus caractersticas las personalizaremos en el Sistema Windows de MS por ser el ms popular. Aunque este conocido sistema ha sufrido paulatinas mutaciones, nos referiremos a las que se implementan en las versiones actuales de 32 bits.
2 El Sistema Operativo
Desde el punto de vista funcional, el Sistema Operativo (SO) es el supervisor de cualquier actividad que se ejecuta en el ordenador. Me gusta decir que el SO viene a ser como el soplo de vida que hace funcionar la mquina. Sin l, el hardware se comparara a un ser humano en coma profundo; quizs con un gran potencial pero incapaz de ninguna accin. Nota: el trmino Sistema Operativo data, de finales de los 50. En toda esta obra nos referimos a l como el "Sistema" (con maysculas) o por su acrnimo "SO". Cuando utilicemos minsculas (el sistema) nos referimos al ordenador como conjunto.
En realidad el SO est constituido por un conjunto relativamente grande de programas; solo hay que considerar la ingente cantidad de espacio necesario para cargar un Sistema Windows actual; incluso en su configuracin mnima (el cdigo de Windows 3.11 tena aproximadamente 500.000 lneas de cdigo, el de Windows 2000 tiene 45 millones). Sin embargo, hablando con propiedad, muchos de estos mdulos no pertenecen al "Sistema", son programas de aplicacin y utilidades adicionales que no tienen que ver demasiado con aqul, sino con tcnicas comerciales y de mrketing. Pero esto... es ya otra historia.
3 Programas de aplicacin
Desde un punto de vista estructural, el software que controla el funcionamiento de un ordenador est organizado por capas ( 1.7a).De estas, el Sistema Operativo es una capa intermedia, situada entre los programas de aplicacin y los controladores de dispositivos ("drivers"). La capa superior, constituida por los programas de aplicacin, es la encargada de realizar tareas directamente utilizables por el usuario. Un procesador de textos, una hoja de clculo, un navegador Web, etc. Son el tipo de programa que, con ms probabilidad, ser objeto de atencin del programador C++ [2]. Una caracterstica de los programas de aplicacin es que estn compilados para un Sistema especfico [10]. Por ejemplo; un procesador de textos WordPefect para Linux correr en cualquier plataforma hardware que tenga cargado dicho sistema, con independencia de su configuracin concreta: Modelo de procesador; tipo de disco; tipo de bus interno; tipo de tarjeta grfica. etc.
4 Controladores de dispositivos
Por su parte, la capa inferior del Software est constituida por unos programas que actan de interfaz entre el hardware y el Sistema Operativo. Son los denominados controladores de dispositivos, porque son ellos los que controlan los dispositivos hardware. Nota: En la arquitectura PC, algunos de estos controladores de dispositivos E/S estn integrados en las rutinas de la BIOS ( H4).
Los "drivers" son especficos de cada elemento hardware y Sistema que deba manejarlo, de forma que para un determinado Sistema existen tantos drivers como dispositivos hardware deba soportar. A la inversa, cada fabricante de hardware, por ejemplo digitalizadores, impresoras, controladoras de disco etc. debe disponer de un controlador especfico para cada modelo y Sistema Operativo distinto con el que deba usarse el modelo en cuestin. Nota: los "drivers" instalables (que se pueden cargar como cualquier otro programa durante la carga inicial del Sistema) se materializan en ficheros [13] y permiten que el SO pueda configurarse segn las caractersticas particulares de la mquina o preferencias del usuario. Su introduccin constituy un factor de flexibilidad y progreso considerable para los SO's. En MSDOS este proceso es controlado con un fichero "Script" denominado CONFIG.SYS.
A principios de los 90 era frecuente que, junto con cada nuevo elemento hardware que se adquiriese, el fabricante aadiera un disquete con los "drivers" para los SOs ms conocidos, por ejemplo, Xenix, Windows 3.1, OS/2 etc. En la actualidad, todava se siguen incluyendo estos programas en forma de disquete o CD. El propio Windows incluye cientos de tales controladores para los modelos de hardware de los fabricantes ms conocidos (incluyendo algunos denominados "Genricos" o estndar); estos controladores son proporcionados a MS por los fabricantes [3].
Los controladores de dispositivo se suelen agrupar en alguna de las siguientes categoras o clases: Adaptadores de audio (tarjetas de sonido). Dispositivos de comunicacin (infrarrojos, mdems, etc). Dispositivos de visualizacin; pantallas (displays). Teclados. Ratn ("mouse" y otros sealadores grficos). Dispositivos multimedia. Dispositivos de Red. Impresoras. Almacenamiento
4 El ncleo
Como el resto del software, tambin el SO est construido por capas. Las interior, la que representa su parte ms ntima, el "Kernel" o ncleo [1], es un programa multihebra que reside permanentemente en memoria. Se ocupa bsicamente de tres tareas primordiales: Gestin de memoria. Gestin de E/S a disco. Control de las tareas en ejecucin.
Desde un punto de vista conceptual, quizs sea esta ltima su actividad principal, de forma que el kernel es antes que nada un gestor de tareas. Conceptualmente, la gestin del almacenamiento (ficheros de disco), denominada genricamente como sistema de ficheros ("File System"), no es una parte fundamental del Sistema. De hecho algunos SOs pueden utilizar ms de uno (o ninguno). Sin embargo desde un punto de vista funcional, la eficacia del "File System" es determinante en el rendimiento global del Sistema Operativo. Actualmente se estn haciendo importantes esfuerzos para mejorar este apartado, y algunos de los avances ms revolucionarios de los futuros SOs vendrn de esta direccin. A ttulo de ejemplo y
como pincelada al respecto, incluimos el principio de un artculo de Leander Kahney: "Searching for the Perfect OS", aparecido en Wired News www.wired.com en Julio del 2004:
It may sound idiotically simple, but according to technology's leading seer, Apple CEO Steve Jobs, searching for information -- not sorting it -- is the wave of the future. At Apple's Worldwide Developers Conference in San Francisco this week, Jobs declared that searching for information on a hard drive, rather than sorting into files and folders, is the future of computing. "We all have a million file folders and you can't find anything," Jobs said during his keynote speech introducing Tiger, the next iteration of Mac OS X, due next year. "It's easier to find something from among a billion Web pages with Google than it is to find something on your hard disk," he added. The solution, Jobs said, is a system-wide search engine, Spotlight, which can find information across files and applications, whether it be an e-mail message or a copyright notice attached to a movie clip. "We think it's going to revolutionize the way you use your system," Jobs declared. In Jobs' scheme, the hierarchy of files and folders is a dreary, outdated metaphor inspired by office filing. In today's communications era, categorized by the daily barrage of new e-mails, websites, pictures and movies, who wants to file when you can simply search? What does it matter where a file is stored, as long as you can find it?
3 La mquina virtual
La descripcin "oficial" de Windows nos dice que es un Sistema grfico, multiprograma y multihebra. Dejando aparte los aspectos grficos, su caracterstica ms notoria para el usuario es su capacidad de multiprogramacin; lo que permite que puedan ejecutarse de forma simultanea y sin interferencias diversas aplicaciones. Para implementar esta capacidad, Windows crea un entorno de ejecucin propio e independiente para cada tarea; es como si cada aplicacin corriese en una mquina independiente, que por esta razn se denomina mquina virtual (MV). Puesto que los dispositivos fsicos son nicos y adems pueden ser distintos en cada mquina, se crean tambin unos dispositivos virtuales (designados de forma genrica como VDs, "Virtual devices") que representan, de forma ideal y normalizada, el "hardware" de las mquinas virtuales. De esta forma se consigue que las MV utilicen un hardware virtual que es independiente del hardware real [4].
Las mquinas virtuales se materializan en una tarea en la que se ejecuta una aplicacin y un determinado software de soporte (los controladores virtuales de dispositivo ), que proporcionan a la aplicacin una simulacin prcticamente perfecta del ambiente que pretenden recrear. La
aplicacin dispone de todos los posibles dispositivos y servicios como si fuesen reales, incluyendo controlador de interrupciones programable PIC ("Programmable interrupt controller" vectores de interrupcin ( servicios de BIOS ( H2.4); servicios de E/S ( H2.4.1); acceso directo a memoria (DMA H2.3), etc. H2); tabla de H3.2); H2.1); memoria; registros de UCP (
Las implicaciones prcticas son trascendentales, porque a fin de cuentas, cualquier programa Windows est pensado para correr en una de estas mquinas virtuales, lo que le hace realmente independiente del hardware. Se consigue tambin que los servicios del sistema, encapsulados en libreras .DLL ( 1.4.4b), puedan escribirse igualmente para un entorno independiente del hardware, ya que proporcionan servicios a mquinas virtuales.
El artificio de la mquina virtual no es nuevo. Los mainframes han utilizado desde siempre tcnicas anlogas para soportar multiprogramacin, pero su aplicacin de forma segura en la informtica personal solo pudo realizarse, cuando a partir del Intel 80386, los microprocesadores dispusieron de determinadas capacidades hardware. Es lo que se conoce como funcionamiento en modo protegido ( H5.1), que presenta una doble ventaja: Simplificar la gestin de estas tareas, que son manejadas por el hardware del procesador en vez de utilizar recursos estrictamente software (el procesador garantiza de forma segura la independencia entre las diversas tareas). Realizar gran parte del control con recursos hardware preconstruidos en el procesador, lo que acelera el rendimiento global del sistema.
4 Dispositivos virtuales
La mquina virtual utiliza recursos virtuales; estos recursos pueden ser elementos hardware o software, aunque de forma genrica los denominamos dispositivos virtuales (VDs). Los VDs son utilizados mediante controladores de dispositivo tambin virtuales VxDs. Observe que los VDs no existen, son en realidad una abstraccin conceptual. Lo que si tiene existencia real son estos controladores virtuales VxDs, representados por ficheros de terminacin .VXD. Estas piezas de software "virtualizan" los mencionados dispositivos, de forma que se comportan hacia la mquina virtual como si estuviese dialogando con un dispositivo hardware real y le proporcionan los mismos servicios que si los dispositivos fsicos estuviesen realmente disponibles. La particularidad es que este hardware es ideal, en el sentido que es normalizado. Por ejemplo, para una aplicacin que corre en una mquina virtual, la controladora de video es siempre la misma, con independencia de cual sea el modelo realmente conectado. As pues, aunque son conceptos distintos, a efectos prcticos los VDs y los VxDs pueden tomarse como sinnimos. Los primeros son abstracciones y los segundos son ejecutables que simulan (virtualizan) dicha abstraccin de forma que parezca que las MVs disponen de ciertos recursos (hardware o software) estndar. Aunque la mayora de los VxDs manejan dispositivos hardware (sus
E/S), otros manejan o reemplazan determinados recursos software, por ejemplo rutinas de ROM BIOS.
Estos dispositivos virtuales son nicos, y compartidos por todas las mquinas virtuales que los necesitan en cada momento. Cualquier dispositivo hardware puede ser utilizado sucesivamente por diversas MVs, de forma que si su estado puede ser alterado al cambiar de una mquina virtual a otra, el dispositivo debe ser utilizado a travs de un controlador virtual, que se encarga de restablecer el estatus a los valores correspondientes. Muchos dispositivos hardware utilizan interrupciones para avisar que los datos estn listos o que ellos mismos lo estn [11]. Los dispositivos virtuales raramente interceptan estas interrupciones por s mismos. En su lugar utilizan el Controlador programable de interrupciones virtual VPICD ello instalan un procedimiento callback ( interrupcin hardware. . Para 1.4.4b2a) que es utilizado por VPICD cuando ocurre una
Como el lector puede suponer, no existe limitacin terica en cuanto a la cantidad o funcionalidad de los VxDs. Los Sistemas Operativos Windows incluyen VxDs que soportan los dispositivos hardware y software ms usuales; adems disponen de las herramientas necesarias para que el usuario pueda crear los que necesite para atender las caractersticas especiales de nuevos dispositivos o modificar los existentes [7]. La realidad es que en ltima instancia, los VxDs de Windows manejan absolutamente todos los dispositivos, desde el sistema de archivos a las tarjetas de sonido y dispositivos de red, ya que proporcionan soporte a un software bsico como son los servicios del sistema (encapsulados en las DLLs). A continuacin se relacionan los que actualmente pueden considerarse como estndar, junto con el acrnimo por el que son conocidos y los servicios que proporcionan: Dispositivo de acceso directo a memoria ("Virtual Direct Memory Access Device" VDMAD) Este dispositivo virtualiza los accesos directos a memoria DMAs ("Direct Memory Access"). El fichero fuente es VDMAD.VXD. Controlador MS-DOS ("DOS manager" DOSMGR) Controlador de dispositivo que virtualiza un Sistema MS-DOS. Intercambiador de pginas de memoria (PAGEFILE y PAGESWAP) Controlador de dispositivo encargado de manejar memoria virtual mediante un mecanismo de intercambio de pginas (page swapping). El fichero fuente es DYNAPAGE.VXD. Controlador programable de interrupciones virtual ("Virtual PIC Device" VPICD) Controlador de dispositivo que virtualiza el controlador programable de interrupciones PIC ("Programmable interrupt controller" H2.4).
Controlador de memoria virtual (V86MMGR) Controlador de dispositivo que virtualiza los modelos de memoria XMS (Extendida) y EMS (Expandida) para aplicaciones que corren en una mquina virtual x86 (V86).
Cargador virtual de dispositivos ("Virtual x Device Loader" VXDLDR) Este controlador es en realidad un servicio para el funcionamiento de las mquinas virtuales, ya que permite cargar y descargar dinmicamente (en tiempo de ejecucin) los propios controladores virtuales (VxDs).
Cache virtual ("Virtual CACHE" VCACHE) Controlador virtual que proporciona servicios de cach ( H5.2).
Coprocesador matemtico virtual ("Virtual Math Coprocessor" VMCPD) Controlador que virtualiza el coprocesador matemtico.
Dispositivo virtual de energa ("Virtual Power Device" VPOWERD) Este dispositivo virtualiza los servicios de ahorro de energa que son estndar en muchos dispositivos actuales. Por ejemplo, placas-base, controladores de disco, etc.
Shell virtual ("Virtual Shell Device" SHELL) Controlador de dispositivo que virtualiza servicios de shell ( 1.7.3). En este caso, el SHELL se refiere a servicios de envo y visualizacin de mensajes, monitorizacin de las propiedades de las mquinas virtuales y comunicacin con otras aplicaciones, en especial con libreras de enlazado dinmico (DLLs).
Interfaz virtual para el temporizador ("Virtual Timer API" VTDAPI) Controlador de dispositivos que virtualiza servicios de temporizado.
Temporizador virtual ("Virtual Timer Device" VTD) Controlador que virtualiza el reloj del sistema.
Servicios virtuales de Windows-32 ("VWIN32 Services" VWIN32) Este controlador que virtualiza servicios de VxDs de Windows 32.
4.1 En realidad, este gestor de mquinas virtuales es el corazn del Sistema Operativo. Su tarea principal es crear, correr y controlar las MVs en las que corren las aplicaciones. Para ello ofrece un servicio de multiprograma preemptivo de tarea nica (single-threaded) en el que el tiempo de UCP se comparte entre las diversas mquinas virtuales. Cuando el VMM arranca, la primera mquina virtual que crea es la Mquina Virtual del Sistema SVM ("System virtual machine"), capaz de contener aplicaciones Windows de 16 bits [5], aunque tambin pueden crearse MVs para programas Win32 y aplicaciones MS-DOS si son necesarias. La SVM puede tener varias hebras de ejecucin, las dems solo pueden tener una. El proceso es como sigue: Inicialmente, el programa WIN.COM carga el fichero VMM32.VXD que contiene el VMM y los controladores virtuales por defecto. El VMM se carga en memoria extendida utilizando un controlador virtual; se inicializa a s mismo y a los controladores virtuales. A continuacin conmuta a un modo de ejecucin protegido [12]. El resultado es que el VMM y los controladores virtuales corren en un espacio contiguo de direcciones de 32 bits (flat model address space) denominado anillo 0 (ring 0). A partir del 80386, los procesadores Intel que "motorizan" los PC's tienen 4 niveles de proteccin interna en forma niveles de privilegio denominados anillos ("Rings") numerados de 0 a 3. El anillo 3 es donde residen las aplicaciones Windows; el anillo 0 es donde reside el cdigo con mayores privilegios. Por ejemplo el kernel del SO y los programas VxDs que pueden manejar directamente los puertos de E/S ( H2.5). Un cdigo del anillo 0 no solo puede interceptar directamente las E/S de cualquier puerto fsico, tambin redireccionarlas en caso necesario, lo que le permite virtualizar o emular cual
0.3 El Hardware
Esta pgina ha sido movida.
Toda la seccin dedicada al Hardware ha sido reestructurada. Consulte la seccin "Tecnologa del PC" en la seccin de Tutoriales de la pgina inicial ( Tutoriales).
1 Programacin C++
"No programming language can be all things to all programers. No matter how many features a language has, there's always someone who wants just one more". Dan Saks "C/C++ Users Journal" Enero 1990.
Afortunadamente parece que las cosas vuelven a su cauce. Hace poco tiempo que algunos se dieron cuenta que el asunto haba empezado a desmadrarse, as que empezaron a quitarle cosas y a simplificarlo..., Estaba naciendo Java! (es tambin la explicacin "oficial" de Microsoft para inventar el C# ;-) Nota: Esta es la situacin por el momento, pero no os preocupis. Vemos como Java se est perfeccionando a marchas rpidas, con lo que a no tardar ser tan complejo como C++ y habr que volver a inventar algo ms sencillo...[4] En cuanto al C#: Sea bienvenida cualquier mejora!!. Aunque se me ocurre que no estara de ms aquello de mantener una cierta "diversidad gentica" en la informtica, mucho me temo que al paso que vamos acabemos todos vestidos de gris con el "Libro Rojo" en el bolsillo :-( [6]
2 Resea histrica
Desde un punto de vista histrico, el C es anterior al C++, aunque el estndar C++ fuera publicado antes que el de C [2], de modo, que paradjicamente el hijo influy en el estndar del padre. As pues, la propuesta de ANSI C recogi algunas de las normas del C++. Ambos nacieron en los prestigiosos laboratorios Bell de la AT&T (American Telephone and Telegraph) en Murray Hill (New Jersey USA) [3]. El primero de la mano de Brian W. Kernighan y Dennis M. Ritchie (la "K" y la "R" de K&R, siglas con las que se les conoce), el segundo es de Bjarne Stroustrup. La primera edicin del libro: "El lenguaje de programacin C" de K&R es de 1978. Por su parte la primera edicin de: "El lenguaje de programacin C++" de Stroustrup es de 1986. El propio Stroustrup reconoce que comenz a trabajar en su diseo en 1979; justo un ao despus de la publicacin del clsico de K&R. Las primeras versiones en uso del lenguaje (bajo el nombre de "C con clases") en el entorno de los departamentos de investigacin de la AT&T se remontan a 1980. La primera utilizacin del lenguaje fuera del entorno de investigacin data de Agosto de 1983. La designacin actual C++ fue acuada en el verano de 1.983 por Rick Mascitti. El primer compilador comercial fue lanzado en Octubre de 1985. Como todos los lenguajes (naturales y de programacin), el C++ es un resultado de la evolucin; de forma que recoge influencia de sus ancestros, algunos de los cuales ya se han sealado ( 0.1). Adems es en s mismo un producto en evolucin. Las ltimas aportaciones datan de los 80, y se refieren principalmente al mecanismo de excepciones y a las plantillas ("Templates"). Sin duda la mejor fuente de informacin sobre la historia y evolucin de este lenguaje es su propio inventor, de modo que remitimos al lector a sus propias palabras D&EC++.
cosas discurren como es de suponer, la aprobacin ocurrir dentro de este ao, as que el prximo estndar ser el C++2011. Nota: a la hora de escribir estas lneas, la ltima revisin publicada lo era bajo el ttulo ISO_C0x_final_draft. Un documento .PDF de nada menos que 11 MB.
Podra decirse que despus de vivir una poca dorada, la popularizacin y uso del C++ haba sufrido una cierta ralentizacin en favor de nuevas modas y nuevos lenguajes, y que incluso su desarrollo y evolucin haban quedado estancados desde los aos 70. Sin embargo, esta aparente "inactividad" ha estado lejos de ser real y el nuevo estndar incluye un sinnmero de avances conceptuales y materiales -en forma de nuevas libreras- que lo colocan de nuevo en una posicin puntera dentro del mundo de la programacin, en especial en lo que respecta a grandes sistemas. Precisamente, la razn principal de los retrasos ocurridos en el proceso de aprobacin del nuevo estndar, tienen mucho que ver con la magnitud, nmero y calado de las nuevas extensiones y libreras. Con independencia de que los cambios se hagan oficiales, muchas de las nuevas herramientas ya estaban en la calle de forma ms o menos oficial, de la mano de los fabricantes de compiladores. De forma que se habla incluso de un "renacimiento" del C++ como herramienta y concepto. En este sentido, es interesante la entrevista de Craig Symonds y Mohsen Agsen, dos profesionales que sin duda gozan de una buena perspectiva del mundo de la programacin actual: "C++ Renaissance" o este otro comentario: "C++ Renaissance: First Symptoms of Contagion in Traditionally Non-Native Teams".
3 Estudiar C++
"C++ should not be for beginners, as it is better to learn the principles from a clearer language than be confused by what all the syntactic knobs and dials, and superfluous constructs do in C++. As for courses, C++ has proven so difficult to learn that you need lots of courses". Ian Joyner "C++??" ( [Joyner-96]).
Para tener una perspectiva histrica parece natural estudiar primero C y despus C++, con lo que se empiezan a ver las diferencias y salvedades entre uno y otro. Este es el enfoque de algunos libros; de hecho el ya comentado manual de ayuda "C++ Builder Languaje Guide" sigue ms o menos esta pauta. Dedica muchos comentarios a las diferencias entre C y C++, y al final dedica un captulo a los asuntos que son exclusivos de este ltimo. Algunos de estos libros incluso hacen comentarios curiosos, que ya solo tienen sentido desde un punto de vista histrico. Por ejemplo, citan que los ficheros fuente de los programas C deben tener nombres con terminacin ".c" y los de C++ terminaciones ".cc" o ".cpp", lo que es superfluo para los compiladores actuales. Por ejemplo, Borland C++Builder puede compilar perfectamente fuentes .c como C o como C++ con un simple indicador (-P) en la orden de llamada. Nota: Otros, como los compiladores GNU C/C++, permiten utilizar ambos criterios. Adems de poder utilizar una directiva explcita, pueden distinguir el tipo de compilacin por la terminacin de los fuentes. Por ejemplo, las terminaciones .c son tratadas y compiladas como fuentes C, mientras que los sufijos .C; .Cpp; .C++; .cc son compilados como C++. Otros compiladores C+
+ Unix como Solaris de SUN o HP-UX pueden compilar fuentes con terminaciones .C, .c, .cc, .cpp o .cxx.
C++ no naci como un lenguaje orientado a objetos puro. Ms bien se trataba de aadirle "objetos" al clsico C de K&R, ya que el nuevo paradigma de programacin "con objetos", se mostraba como un paso adelante en el arte de la programacin. De hecho, aunque C++ introduce nuevas palabras clave y operadores para manejo de clases, algunas de sus extensiones tienen aplicacin fuera del contexto de programacin con objetos (fuera del mbito de las clases). Esta es tambin la causa de que C++, junto con las magnficas cualidades del C, arrastre algunas de sus deficiencias. Sigue siendo permisivo (aunque menos) "intentando hacer algo razonable con lo que se haya escrito", solo que a veces, sin que nos demos cuenta, se pasa de listo. Por supuesto, con ambos lenguajes resulta cierto el viejo aforismo informtico: "Un programa no hace lo que queremos que haga, sino lo que le hemos dicho que haga". En el caso del C++ quizs tendramos que aadir: "Mas lo que l decide por su cuenta"... :-) Cuando se trata de programas sencillos, que no requieren necesariamente de las caractersticas "++" de la POO, surge inmediatamente la cuestin si ser mejor hacerlo en C o en C++, Cual es mas rpido? Cual proporciona un cdigo ms compacto? Segn dicen los expertos, con los actuales compiladores el resultado est en tablas. Las diferencias se mantienen en un margen de 5% y por lo general los resultados se encuentran a la par. Sin embargo, en cuanto se trata de escribir programas algo ms complicados que mostrar el consabido "Hola mundo", las diferencias de productividad son notables, con una indiscutible ventaja a favor del C++. Nota: En cierta forma esta discusin, usar C++ o C, es un poco bizantina, dado que a efectos prcticos el segundo es un subconjunto del primero (de hecho, los compiladores GNU C y C++ estn integrados en un solo producto). Ms bien cabra discutir si, utilizando C++, merece o no la pena usar los recursos de la POO.
Dicho esto queda una cuestin: Aunque estudiar C++ a partir de C proporciona una perspectiva histrica, una visin del desarrollo del lenguaje, de como fueron sucediendo las cosas. En mi opinin, hacerlo de esta forma no solo es innecesario sino quizs contraproducente para el estudiante normal. No digo que est de ms, solo que es un camino innecesariamente farragoso. Me parece que se trata de una situacin parecida a la de alguien que quisiera aprender Espaol empezando por aprender Latn. Por supuesto no estara de ms si tiene tiempo y gana, si se es un lingista. Se tendr un mayor conocimiento del lenguaje y su evolucin; se comprender mejor el porqu de ciertas cosas. Pero para el extranjero que simplemente necesita entenderse en Espaol, es evidentemente innecesario. Digo esto, porque al ser la POO un paso superior de abstraccin respecto de los primeros sistemas de "traslacin de frmulas". Un paso en la evolucin de los lenguajes de programacin, con un cuerpo de doctrina ya suficientemente consolidado y coherente, las cosas pueden explicarse partiendo directamente del estudio de C++ y aprovechando todas sus posibilidades desde el principio. Incluso dira que intentando "olvidarse" del viejo C que an pervive en su interior. Es perfectamente factible introducir el concepto general de clase y objeto, para decir despus que las estructuras son una "clase" especial que tiene estas y las otras propiedades (todas sus propiedades son pblicas), sin necesidad de introducir el concepto tradicional de "estructura" C, para luego decir que en C++ son un tipo especial de clase... Esto tendr la ventaja adicional de permitir al nefito empezar a pensar "en objetos" con ms rapidez.
Nota: Tena ya una gran cantidad de material recopilado cuando me di cuenta de esta realidad, as que tuve que volver a rehacer una parte de la estructura de este "libro", volviendo a empezar directamente con el C++, e intentando hacer la menor cantidad de referencias al viejo C. A la hora de escribir estas lneas todava no est terminado el trabajo (no se si lo estar algn da), pero esta es la intencin, de forma que si cuando caiga en manos del lector quedan referencias al viejo C, que no sean meramente histricas o comparativas, sepa que se debe simplemente a un trabajo inacabado. Inicio. [1] Ya sabis que esta tienda on-line tiene una caracterstica (que se va extendiendo a otras muchas): Los lectores pueden incluir comentarios y opiniones personales sobre los libros. Tiene la ventaja de que no son comentarios interesados de la editorial. Si sabemos leer entre lneas, esta posibilidad puede ser de mucha ayuda a la hora de evaluar el libro. Sin embargo, la mejor fuente de informacin (en ingls) sobre C++, incluyendo evaluacin de libros, es la Asociacin de usuarios C y C++ ACCU (The Association of C and C++ Users), seccin "Book reviews".
[2] El instituto ANSI (American National Standards Institute) estableci en 1.989 el comit denominado J16 para estandarizar el C++. Paralelamente, la organizacin internacional encargada de los estndares ISO (International Standards Organization www.iso.ch), haba creado el comit WG14 que trabajaba en el mismo sentido. Finalmente, el comit americano recomend que se adoptara el estndar ISO como estndar americano. La primera versin del Estndar data de principios de 1997; la ltima (por el momento) se ratific en Marzo de 1998, y se public en Septiembre del mismo ao por el ANSI y el ISO. De forma que el "Estndar C++" es la norma ISO/IEC 14882 (IEC es acrnimo de "International Electrotechnical Commission", uno de los grupos de trabajo del ANSI). La Norma est disponible para descarga en un documento .PDF de 2.794 KB y 732 pginas, previo pago de unos 18 $ US: National Committee for Information Technology Standards (puede pagarse con tarjeta de crdito). La versin impresa es mucho ms cara!!. Tambin puede descargarse gratis uno de los ltimos borradores conocidos como DWPs ("Draft Working Papers"): ftp://ftp.research.att.com/dist/c++std/WP/CD2. Hay que advertir no obstante, que la Norma dista mucho de ser un texto adecuado para aprender C++. [3] "Bell Labs"; durante mucho tiempo los mayores y mejores laboratorios de investigacin industrial del mundo. Adems del origen de los lenguajes C y C++, entre otras "naderas", fueron tambin la cuna del transistor; del Sistema Operativo UNIX, y de las primeras clulas fotovoltaicas con utilidad prctica. [4] Mucho despus de escribir esta nota, he encontrado esta confirmacin: "I predicted the growth of Java complexity and don't condemn it, I consider complexity an inevitable consequence of serving a large community". Bjarne Stroustrup "The State of the Languaje".
[5] Como lectura complementaria tambin recomendara: "La Ley de Murphy", de Arthur Bloch. Ed. Temas de Hoy S.A. Madrid. Una de mis lecturas favoritas y sin duda un buen libro "de cabecera" para los programadores C++.
[6] Si no entiendes la referencia no te preocupes... Sencillamente eres demasiado joven!. [9] Hace poco lea el comentario del directivo de una gran multinacional, quejndose que el tiempo de entrenamiento estimado para que un programador C++ fuese verdaderamente eficiente era de tres aos, mientras que la NASA estimaba en 18 meses el tiempo de preparacin de un astronauta.
con la importante novedad de incluir tambin las herramientas necesarias para su manipulacin; es decir: operadores y funciones de la programacin tradicional. Dicho de otro modo: los nuevos tipos de datos pueden ir acompaados de su "lgebra"; 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, tambin los algoritmos necesarios para su manipulacin (sus operaciones), de forma que pueda ser vista desde el exterior (el programador que las usa) como un ente al que se le envan preguntas u rdenes y responde con el resultado [2]. Este comportamiento de la clase frente al mundo exterior es lo que se llama su interfaz o protocolo. Cmo 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 clsico: Supongamos que en un programa tradicional hay que manejar nmeros complejos. La solucin 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 mdulo m tenemos que hacer: m = SQRT( (Rr * Rr) + ( Yr * Yr) )
as sucesivamente para cualquier manipulacin 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 informacin necesaria para realizar todas las operaciones permitidas en el lgebra de los nmeros complejos. No solo la suma, tambin la asignacin, la comparacin, el clculo del mdulo, etc. Incluso los procedimientos para crear elementos nuevos (complejos) y para destruirlos (eliminarlos de la memoria). Ahora el funcionamiento sera 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. Fjese 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 genrico de "nmero entero"). En el ejemplo suponemos que R1, Y1, R2, Y2 siguen siendo nmeros fraccionarios tradicionales, los mismos que en el ejemplo anterior. Fjese tambin que la asignacin x = (R1, Y1) supone que el compilador sabe que al ser x un complejo, el smbolo "=" no representa aqu la misma operacin que en el caso de, por ejemplo, z = 6; tambin supone que el compilador sabe que significa exactamente la expresin (R1, Y1) a la derecha.
Si ahora queremos calcular el resultado de la suma de los dos complejos y el valor de su mdulo, solo tenemos que hacer: Cc z = x + y; float m = z.mod();
Observe que en la primera lnea 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 operacin "suma" entre sus elementos y le hemos asignado el operador "+"). Por otra parte, en la segunda lnea solo tenemos que mandarle al complejo z el mensaje mod() - calcula el mdulo -; la sintaxis es la sealada: z.mod(). Ya sabemos que el resultado es un escalar y lo asignamos al nmero fraccionario m. Fjese tambin que en ambas lneas el operador de asignacin "=" no representa la misma operacin. En la primera se trata de una asignacin entre complejos; en la segunda es la tradicional asignacin entre nmeros fraccionarios. Esta capacidad "camalenica" de los operadores es tpica de la POO, y se conoce como sobrecarga [4] (veremos que tambin puede haber sobrecarga de funciones). El compilador sabe en cada momento que operador debe utilizar de toda la panoplia disponible aunque estn bajo el mismo smbolo; lo sabe por el contexto (por la naturaleza de los operandos involucrados). En la POO es frecuente que mtodos anlogos 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 mtodo para calcular el mdulo se denomine mod() en las tres clases. Aunque el resultado sea un nmero 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 confusin en el programa porque cuando apliquemos el mtodo en cada caso concreto, el compilador sabe a cual de ellos nos estamos refiriendo en base a los objetos involucrados. Esta caracterstica 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 cdigo. Cada vez que encontremos una invocacin al mtodo mod tenemos una imagen mental del resultado con independencia del objeto concreto al que se aplique. Llegados a este punto, introduciremos algn vocabulario especfico para adaptarnos a la terminologa, algo especial, que utiliza la POO: En vez de "variables" como en la programacin clsica, 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 manipulacin contenidas en las clases (bajo la forma de funciones) reciben el nombre de mtodos. Siguiendo con el ejemplo anterior, en vez de referirnos a funcin mod(), que calcula el mdulo, diremos que mod es un mtodo de la clase de los complejos. En lenguajes como C++, que puede tener elementos de ambos mundos, de la programacin tradicional y de la POO, poder utilizar indistintamente los vocablos "funcin" o "mtodo" 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 prrafos anteriores hemos dicho: "... estos objetos son casos concretos del nuevo tipo, la clase de los complejos..."; utilizando la terminologa correcta diramos: "... estos objetos son instancias de la clase de los complejos...". Como puede verse, instancia significa una sustanciacin concreta de un concepto genrico (la clase). En el mismo sentido podramos decir que el nmero 5 (un objeto), una instancia de la clase de los nmeros enteros, que tiene a su vez determinados mtodos; en este caso las conocidas operaciones aritmticas: suma, resta, multiplicacin..., as como las operaciones de asignacin, la comparacin, etc. Siguiendo este criterio, la expresin: Cc x = (R1, Y1) no se dice: "declaracin de x como objeto de la nueva clase". Es ms correcto sealar: "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 operacin (crear un objeto) est encomendada a un tipo especial de mtodos denominados constructores. Siguiendo con nuestro ejemplo, podemos suponer que la expresin: 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 funcin (mtodo) de Cc cuya misin es precisamente crear objetos segn ciertos parmetros que son pasados como argumentos de la funcin. En ocasiones, cuando se quiere distinguir entre los valores y funcionalidades genricos (de las clases) y los concretos (de los objetos), se suelen emplear las expresiones: propiedades de clase y mtodos de clase para las primeras, y propiedades de instancia y mtodos de instancia para los segundos. As mismo, cuando se quiere distinguir entre una funcin normal (de la programacin tradicional) y una funcin perteneciente a una clase (un mtodo de la clase), se suele emplear para esta ltima la expresin funcin miembro (se sobreentiende "funcin miembro_de_una_clase") [1]. Como puede suponerse, el encapsulamiento, junto con la capacidad de sobrecarga, constituyen en si mismos una posibilidad de abstraccin para los datos mayor que la que facilitaba la programacin tradicional. Ya s puede pensarse en un complejo como algo que tiene existencia "real" dentro de nuestro cdigo ya que lo tratamos (manipulamos) como ente independiente con caractersticas propias; de forma parecida a la imagen que de l tenemos en nuestra mente. Con ser lo anterior un paso importante, sin embargo, las mejoras de la POO respecto de la programacin clsica no terminan aqu. Los Lenguajes Orientados a Objeto como el C++, adems de los tipos de datos tradicionales, incluyen algunas clases pre-construidas, pero debido al hecho de que la "construccin" de un nuevo tipo de variable (como la clase Cc de los complejos en el ejemplo anterior) requiere un cierto trabajo de programacin inicial para disear la clase, se pens que sera estupendo poder aprovechar el trabajo realizado en determinados diseos para, a partir de ellos, obtener otros nuevos de caractersticas ms o menos parecidas. Se trataba en suma de intentar reutilizar el cdigo 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 dot al lenguaje de dos nuevas capacidades: la Herencia y la Composicin.
Por herencia ("Inheritance") se entiende la capacidad de poder crear nuevas clases a partir de alguna anterior, de forma que las nuevas "heredan" las caractersticas de sus ancestros (propiedades y mtodos). Se trata por tanto de la capacidad de crear nuevos tipos de datos a partir de los anteriores. Una caracterstica especial de la herencia es que si se cambia el comportamiento de la clase antecesora (tambin llamada padre, base o super), tambin cambiar el comportamiento de las clases derivadas de ella (descendientes). Como puede deducirse fcilmente, la herencia establece lo que se llama una jerarqua de clases del mismo aspecto que el rbol genealgico de una familia. Se entiende tambin que estos conceptos representan niveles de abstraccin que permiten acercar la programacin a la realidad del mundo fsico tal como lo concebimos. Por ejemplo, entendemos que un motor elctrico deriva de la clase general de los motores, de la cual derivan tambin los de gasolina, diesel, vapor, etc. y que, sin dejar de ser motores, cada subclase tiene sus caractersticas peculiares. Por supuesto que no tendra ningn sentido utilizar la herencia para crear simplemente un clnico 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 continuacin, perfilar los comportamientos o datos que queremos pulir en la nueva versin 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 especficas del caso. Por lo general esta modificacin de la interfaz se consigue de dos formas: 1. Aadiendo propiedades y/o mtodos que no existan en la clase base 2. Sobrescribiendo propiedades del mismo nombre con distintos comportamientos (sobrecarga y/o polimorfismo).
Aunque la herencia es uno de los pilares de la POO, tiene tambin sus inconvenientes. Por ejemplo, dado que el compilador debe imponer ciertas caractersticas en tiempo de compilacin sobre las clases creadas por herencia, esto resulta en cierta rigidez posterior. Sin embargo, como hemos visto, una de sus ventajas es la reutilizacin del cdigo.
La composicin (tambin llamada herencia mltiple) es la segunda va para crear nuevas clases a partir de las existentes. Por composicin 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 ms clases antecesoras. Siguiendo con el smil de la carta circular, la composicin equivaldra a escribirla reutilizando trozos de cartas anteriores. Es clsico el ejemplo de sealar que podramos 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 climatizacin respectivamente. Este sistema tiene tambin sus ventajas e inconvenientes, pero es muy flexible, ya que incluso pueden cambiarse los componentes en tiempo de ejecucin.
2 Resumen:
Como resumen de este rpido repaso, podemos sealar que la Programacin Orientada a Objetos (POO) tiene sus propios paradigmas y ventajas, entre las que destaca la reutilizacin del cdigo. A los acadmicos 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 implementacin, o dicho en otras palabras: no es necesario conocer los detalles de cmo estn implementadas las propiedades para poder utilizarlas. Los objetos funcionan a modo de caja negra en la que estn empaquetados los datos y las instrucciones para su manipulacin, 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 mltiple. Sobrecarga: Posibilidad de crear diferentes mtodos dentro de una clase que comparten el mismo nombre, pero que aceptan argumentos diferentes y se comporten de forma distinta segn la naturaleza de estos argumentos ( 4.4.1a).
Polimorfismo Es una caracterstica que resulta de gran ayuda en programacin pues facilita la claridad y consistencia del cdigo, aunque es un concepto bastante genrico (y frecuentemente malinterpretado). Se conoce con este nombre el hecho de que un mtodo tiene el mismo nombre y resulta en el mismo efecto bsico pero est implementado de forma distinta en las distintas clases de una jerarqua.
3 Bibliografa:
Para una ms detallada exposicin sobre los conceptos involucrados en la POO y su relacin con el C++, sugerimos dos referencias: "Thinking in C++" ( Bruce Eckel) y "What is Object-Oriented Programming?" ( Stroustrup), aunque desafortunadamente ambas en ingls. La primera bastante didctica enfocada a los aspectos "++" del C; la segunda algo ms terica pero con la autoridad que le confiere ser del inventor del C++. Inicio. [1] Si en principio le parece confusa toda esta terminologa no se preocupe; lo esencial son los conceptos, puede seguir pensando en trminos de "variables" y "funciones". Poco a poco los nuevos vocablos "propiedades", "mtodos", "instancias", etc. irn fluyendo por s solos. En cualquier caso, tenga en cuenta que la terminologa utilizada en la POO es utilizada a veces de forma no demasiado consistente, lo que puede inducir a confusin durante el trnsito de la programacin tradicional a la POO. En otras ocasiones, en especial en algunos textos universitarios, se cuidan en exceso el rigor y el formalismo con lo que se tienen textos elegantsimos e irreprochables con los que es casi imposible enterarse de que se trata.
[2] Por esta razn, en la literatura forense pueden encontrarse frases como las siguiente: "Un mensaje es una peticin que se hace a un objeto para que aplique uno de sus mtodos". En realidad es la otra forma de decir que se invoca una funcin de una clase desde una de sus instancias (un objeto). Debemos reconocer que esta forma de expresar el comportamiento de los objetos, cuando se explican sus funciones miembro refirindose a ellas como "mensajes" que se lanzan a los objetos, es muy del gusto de los partidarios de la POO, de forma que Bruce Eckel ( Thinking in C++) llega a afirmar que: "La POO puede resumirse en una sola frase: Enviar mensajes a objetos", y que cuando se ha asumido esto, el uso de C++ resulta sorprendentemente sencillo. Gran parte de esta terminologa proviene en realidad de Smalltalk. Uno de los primeros lenguajes orientados a objeto desarrollado en el hoy legendario PARC "Palo Alto Research Center" de Xerox en California, donde nacieron muchas de las ideas que hoy pueblan el mundo de la informtica. [3] Precisamente el hecho de poder incluir funciones en las estructuras es la sntesis del avance que supuso C++ frente al C clsico ( 0.Iw1). 4.9).
1 Generalidades
C++ es un lenguaje imperativo orientado a objetos derivado del C [1]. En realidad un superconjunto de C, que naci para aadirle cualidades y caractersticas de las que careca. El resultado es que como su ancestro, sigue muy ligado al hardware subyacente, manteniendo una considerable potencia para programacin a bajo nivel, pero se la han aadido elementos que le permiten tambin un estilo de programacin con alto nivel de abstraccin. Nota: estrictamente hablando, C no es un subconjunto de C++; de hecho es posible escribir cdigo C que es ilegal en C++. Pero a efectos prcticos, dado el esfuerzo de compatibilidad desplegado en su diseo, puede considerarse que C++ es una extensin del C clsico. La definicin "oficial" del lenguaje nos dice que C++ es un lenguaje de propsito general basado en el C, al que se han aadido 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 librera (en realidad la librera Estndar C es un subconjunto de la librera C++). Respecto a su antecesor, se ha procurando mantener una exquisita compatibilidad hacia atrs por dos razones [2]: poder reutilizar la enorme cantidad de cdigo C existente, y facilitar una transicin lo ms fluida posible a los programadores de C clsico, de forma que pudieran pasar sus programas a C++ e ir modificndolos (hacindolos ms "++") de forma gradual. De hecho, los primeros compiladores C++ lo que hacan en realidad era traducir (preprocesar) a C y compilar despus [3] (las consecuencias se dejan sentir todava en el lenguaje 1.4.2).
Por lo general puede compilarse un programa C bajo C++, pero no a la inversa si el programa utiliza alguna de las caractersticas especiales de C++. Algunas situaciones requieren especial cuidado. Por ejemplo, si se declara una funcin dos veces con diferente tipo de argumentos, el compilador C invoca un error de "Nombre duplicado", mientras que en C++ quizs sea interpretado como una sobrecarga de la primera funcin (que sea o no legal depende de otras circunstancias). Como se ha sealado, C++ no es un lenguaje orientado a objetos puro (en el sentido en que puede serlo Java por ejemplo), adems no naci como un ejercicio acadmico de diseo. Se trata simplemente del sucesor de un lenguaje de programacin hecho por programadores (de alto nivel) para programadores, lo que se traduce en un diseo pragmtico al que se le han ido aadiendo todos los elementos que la prctica 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 caractersticas son precisamente una cualidad. De hecho, en el diseo de la Librera Estndar C++ ( 5.1) 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 programacin extraordinariamente flexible (programacin genrica). Aunque C++ introduce nuevas palabras clave y operadores para manejo de clases, algunas de sus extensiones tienen aplicacin fuera del contexto de programacin con objetos (fuera del mbito 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, tambin puede hacer que ciertos errores sean difciles de descubrir" ( Shildt). Respecto al C++ podramos decir otro tanto, pero hemos de reconocer que su sistema de deteccin de errores es mucho ms robusto que el de C, por lo que algunos errores de este sern rpidamente detectados. Desde luego, C++ es un lenguaje de programacin extremadamente largo y complejo; cuando nos adentramos en l parece no acabar nunca. Justo cuando aprendemos un significado descubrimos que una mano negra ha aadido otras dos o tres acepciones para la misma palabra. Tambin descubrimos que prcticamente no hay una regla sin su correspondiente excepcin. Cuando aprendemos que algo no se puede hacer, hay siempre algn 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 xito desde su creacin. De hecho, muchos sistemas operativos [4], compiladores e intrpretes han sido escritos en C++ (el propio Windows y Java). Una de las razones de su xito es ser un lenguaje de propsito general que se adapta a mltiples situaciones. Para comprobar el xito e importancia de los desarrollos realizados en C++ puede darse una vuelta por la pgina que mantiene el Dr. Stroustrup al respecto: www.research.att.com. Tanto sus fervientes defensores como sus acrrimos detractores han hecho correr ros 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 justificacin para el diseo de otros lenguajes que intentan eliminar sus inconvenientes al tiempo que mantener sus virtudes (C# y Java por ejemplo), y una de sus ltima incorporaciones, las plantillas ( paradigma de programacin (metaprogramacin). 4.12), ha sido origen de un nuevo
En mi opinin, cualquier lenguaje de propsito general que como C++, permita tocar ambos mundos, la programacin de bajo nivel y altos niveles de abstraccin, resultar siempre e inevitablemente complejo. Ocurre lo mismo con los lenguajes naturales que son tambin extraordinariamente complejos (esto lo saben bien los gramticos). Cualquier comunicacin entre humanos presupone una ingente cantidad de conocimientos y suposiciones previas entre los interlocutores. A pesar de lo cual, la comunicacin exacta y sin ambigedades entre dos personas no resulta fcil.
punteros a funciones-miembro ( 4.2.1g) o Tenga en cuenta lo sealado respecto al rendimiento al tratar de: o Sustituciones inline en funciones definidas por el usuario ( 5.1 Funciones y macros) 4.4.6b) Preste atencin al modo de uso de aquellas funciones de librera que se presentan en dos versiones (
Los compiladores modernos permiten fijar que criterio de optimizacin ser dominante: La velocidad de ejecucin o el tamao. Tanto Borland C++ ( 1.4.3) como MS Visual C++ utilizan la misma
convencin de llamada para este propsito (opciones -O2 o -O1 respectivamente). Por su parte, GNU gcc dispone de varias opciones de optimizacin. En particular, la opcin -Os adopta las medidas tendentes a reducir el tamao del cdigo resultante. Nota: Aparte de las decisiones de optimizacin que puedan adoptar automticamente los compiladores y las reglas de precaucin anteriores, las modernas "suites" ofrecen herramientas de anlisis que permiten conocer de forma objetiva como es la utilizacin de recursos dentro del programa, de forma que se puedan adoptar precauciones en las zonas que resulten ms costosas, y concentrar nuestros esfuerzos de optimizacin en la zonas donde resulten ms provechosos. El compilador GNU cpp dispone de la utilidad gcov, que ofrece estadsticas para analizar el rendimiento del cdigo. Entre otros datos: Cmo se ejecuta cada lnea de cdigo Qu lnea se est ejecutando actualmente. Cuanto tiempo consume cada seccin de cdigo Posibilidad de anlisis a nivel de fichero o de funcin
Inicio. [1] Los lenguajes imperativos son aquellos en los que se especifica cmo conseguir los objetivos que se persiguen. C; C++; Javascript y Perl, entre otros muchos, pertenecen a esta categora. Por contra, los lenguajes declarativos son aquellos en los que se especifica que objetivo se persigue, sin preocuparse por el cmo. SQL y HTML son quizs los ejemplos ms representativos de esta categora. [2] El propio Stroustrup reconoce en el prlogo de su primer libro sobre C++: "Se ha dado gran importancia a mantener compatibilidad con C .... C++ debe la mayor parte a C. C es mantenido como un subconjunto" ( Stroustrup 1987).
[3] De hecho, el mentado compilador Zortech C++, se ofreca como: "The World's first 'TRUE' C++ compiler for MS-DOS". [4] Stroustrup seala que una de las razones que llevaron a K&R a disear el C fue no tener que programar en ensamblador (*), y que en el diseo de C++ se cuid no perder las ventajas ganadas en este sentido. Precisamente comenz a desarrollar C++ como un lenguaje que le ayudara en el trabajo de diseo de un Sistema Operativo distribuido. (*) En ocasiones, C ha sido considerado como un "lenguaje ensamblador de alto nivel". [5] "You are not doing OO just because you are compiling with C++" Ian Joyner "C++??" ( [6] Bjarne Stroustrup. Entrevista con Al Stevens en Dr. Dobb's Journal Sept. 1992. [7] Entrevista en "C++ Pointers and Dynamic Memory Management" de Michael C. Daconta. Edit. John Wiley & Sons, Inc. ISBN 0-471-04998-0 7).
1 Sinopsis
La estructura de un programa es una cuestin que puede ser abordada desde varios puntos de vista, en este captulo consideramos solo dos: Componentes lgicos: se refiere a los diversos elementos que componen una aplicacin, desde los ms complejos hasta los ms simples. Si comparamos un programa con un edificio, los elementos iran desde el edificio como un todo, a los ladrillos (sus elementos ms pequeos) 1.3.1. Almacenamiento: se refiere a como estn alojadas sus partes en la mquina que lo ejecuta. Esta cuestin puede ser abordada desde dos perspectivas: Organizacin lgica. Comprende las caractersticas de los diversos tipos de almacenamiento que se distinguen en un programa C++ ( 1.3.2).
Organizacin fsica. Toma en consideracin los diversos dispositivos fsicos utilizados por el programa para alojarse l mismo y sus datos ( 2.2.6).
1 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 mquina mediante una serie de algoritmos que definirn 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 aqu se denominan cdigo fuente, vienen acompaadas de algunos datos en forma de texto o imgenes, contenidas en uno o varios ficheros denominados ficheros de recursos ("resources"). Sin embargo, las instrucciones y recursos solo pueden ser utilizadas por la mquina despus de un proceso de traduccin que es realizado por la propia mquina (puede ser distinta de la que ejecuta el programa). El proceso exige que el cdigo fuente sea transformado en una nueva secuencia de instrucciones segn un nuevo sistema de codificacin (el lenguaje mquina), y que los recursos adopten una disposicin 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 mquina. En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real, o de una abstraccin que hemos imaginado; y es de tipo genrico. Se pretende que la mquina se comporte como una funcin que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinacin de las condiciones de entrada.
3 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 E&O insurance is going to cover the legal fees for the lawsuit you've gotten yourself into or merely the settlement cost. Or, if you're 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" www.joelonsoftware.com
"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 they're 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 tpica obviedad que a veces se pasa por alto. Hemos dicho que escribir un programa es establecer el comportamiento de una mquina; parece lo ms natural del mundo enterarse primero de cual es ese comportamiento. Tener una imagen mental lo ms clara posible de las caractersticas de lo que pretendemos modelar. Esta cuestin es lo que los tericos denominan el "espacio" del problema, "'What' domain" en la literatura inglesa. A esta fase se la suele denominar anlisis, y mi consejo particular es que despus de una primera toma de contacto, el segundo paso sea definir de la forma ms detallada posible el principio y el final del problema. Es decir: cual es la informacin de partida (incluyendo su formato y en que soporte se recibe) y cual es la informacin final y en que soporte se proporcionar; no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analgico-digital nos suministra una determinada seal (por citar algn ejemplo). Normalmente en ambas cuestiones tiene mucho que decir el cliente [2], es lo que se llama especificacin; 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 diseados los ficheros se tendrn dos terceras partes -ver a continuacin-. Este sistema tiene adems la ventaja de poner inmediatamente de manifiesto las indefiniciones de partida; a veces los clientes no saben exactamente qu desean y hay que ayudarles a centrar el problema. Dentro de esta fase tiene especialsima importancia el tema de los lmites; esto se refiere al orden de magnitudes que se manejarn. De que rango sern las magnitudes numricas? Podrn adoptar valores negativos? Hay informacin alfanumrica? Como son de largas estas cadenas?. Especialmente si el programa implica diseo de archivos (como es casi seguro), Cual podr llegar a ser su tamao dentro de la vida del programa?. Si se manejan ficheros u objetos binarios, Como
son de grandes? Que concepto tiene el cliente de los que sera "rpido" o "lento"? (milisegundos, minutos, horas?). En esta fase sea especialmente precavido y no se crea a pi juntillas todo lo que le digan (intente hacer de abogado del diablo). Como postre, disee las lneas maestras de una estrategia de recuperacin de errores de ejecucin, incluyendo que har con los no recuperables (errores fatales). Piense por ejemplo que si algn da lo llaman para ver "que ha pasado", quizs le interese disponer de un volcado de texto ASCII en el disco con una descripcin del estatus del programa como parte de las funciones de salida ( 1.5). Hoy da, cuando se empieza a hablar de frigorficos que avisarn de que faltan provisiones o de lavadoras que avisarn al tcnico si se estropean, no estara de ms que sus programas estuviesen a la altura de las circunstancias.
Teniendo ya una imagen ms o menos clara de lo que har su programa, si ste es mediano o grande, es posible que todava tenga que realizar una labor previa antes de ponerse a escribir el cdigo: disear a grandes rasgos cuales sern los mdulos del programa; mdulos que se correspondern aproximadamente con la distribucin del cdigo en ficheros fuente independientes. Quizs tenga que decidir tambin si algunas partes aparecern como libreras [1]. Recuerde lo indicado al respecto al tratar de los Subespacios de Nombres ( 4.1.11).
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 mdulos. En estos casos, el anlisis, la especificacin, la subdivisin en partes (con sus especificaciones particulares), y la asignacin de estas como tareas a los programadores, lo habr realizado el jefe de programacin y desarrollo.
5 Escribir el cdigo
Suponiendo cumplimentados los pasos anteriores, el programador est en condiciones de construir una imagen mental clara de como ser esa conexin entre la informacin de entrada y la salida, es lo que se denomina "espacio" de la solucin ("'How' domain"); su forma concreta es justamente el fuente del programa que se pretende. La codificacin consiste justamente trasportar a papel (en el lenguaje de programacin elegido) la imagen mental de esa conexin.
Para escribir el cdigo fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres US-ASCII ( 2.2.1a). Son los siguientes [8]:
/ ^ & | ~ !
Caracteres no-imprimibles denominados separadores Espacio horizontal; Tabulacin horizontal (TAB); Tabulacin vertical (VT); Salto de forma (FF); Nueva lnea (NL). Nota: Para escribir el cdigo solo hace falta un editor de texto plano, aunque las modernas "suites" de programacin incluyen editores especficos que estn conectados con el depurador, el compilador el enlazador (ver ms adelante) e incluso el sistema de ayudas, de forma que, por ejemplo, pueden mostrarnos automticamente la sentencia en la que se ha producido un error de compilacin, o la pgina correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente). Tambin muestran en diversos colores las palabras clave, los comentarios, Etc. Los ms avanzados disponen incluso de opciones que podramos calificar de "inteligentes", en el sentido que pueden prever cual ser nuestro prximo movimiento en funcin de la sentencia que estamos escribiendo (por ejemplo, ofrecernos una lista de las propiedades y mtodos de una clase si nos estamos refiriendo a ella). Durante la fase de escritura no desdee dos puntos: Incluir la mayor cantidad de comentarios y aclaraciones posibles. Cuando se est muy "metido" en el programa todo parece evidente, pero piense que tiene que retocarlo dentro de unos aos, quizs entonces le parezca "Chino" y agradecer haber dejado la mayor cantidad de documentacin y aclaraciones al respecto. Incluso si es seguro que no volver a verlo, piense en el sufrido programador que le seguir si tiene que habrselas con su cdigo. En este sentido C++ no es precisamente COBOL, aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 3.1). No caiga tampoco en el error de pensar que esa informacin ya est en la documentacin escrita que le han obligado a entregar junto con los fuentes; posiblemente dentro de unos aos Usted mismo no encuentre esos documentos. Incluir la mayor cantidad posible de rutinas y condiciones de comprobacin de errores. Piense que el operador es un "manazas" o que los datos pueden venir con alguna corrupcin, error de transmisin, etc. Verifique constantemente que las condiciones son las esperadas ( 1.4.5).
Una vez que se tiene el cdigo fuente (en uno o varios mdulos), el proceso de traducirlo a instrucciones comprensibles por el procesador (lenguaje mquina) puede hacerse siguiendo dos modelos: los intrpretes y los compiladores [3]. En el caso de lenguajes compilados como C++, el fichero de texto plano (ASCII 2.2.1a) que contiene el fuente del programador (con la terminacin .C .CPP), es sometido a un proceso de varias fases que terminan en la obtencin del ejecutable. De forma genrica, todo este proceso se denomina "compilacin", aunque es una generalizacin un tanto incorrecta, ya que la compilacin propiamente dicha es solo una de las etapas intermedias. Sera ms correcto decir "construccin" del ejecutable, aunque por la extensin y generalizacin de su uso seguiremos utilizando el trmino genrico "compilacin" para referirnos a l. Los procesos de construccin del ejecutable se esquematizan en la figura que comentamos a continuacin:
6 Preproceso
En la primera fase de la compilacin; un programa especial, denominado make, es encargado de iniciar el proceso llamando a los diversos mdulos que se encargan de la construccin del ejecutable (en 1.4.0 se amplan detalles sobre esta parte del proceso). El primero de estos mdulos es el preprocesador. El preprocesador ( 1.4.1) estudia el texto buscando directivas de preprocesado ( 4.9.10), 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 compilacin ( 1.4.2).
7 Anlisis sintctico
Puesto que el fichero fuente est 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 anlisis ("Parsing") es realizado por el analizador sintctico [10]. En esta fase se realizan comprobaciones como que los parntesis estn cerrados, que no aparecen expresiones incompletas, etc. Para realizar esta labor, el "parser" debe identificar los tokens ( 3.2), de forma que el fuente es tokenizado, esto es, reducido a tokens y separadores. El fuente es escaneado, el analizador sintctico (parser) extrae los tokens, seleccionando el que coincida con la secuencia de caracteres ms 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 sera un identificador). Los separadores (whitespaces) es el nombre genrico 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 despus de esto cualquier separador redundante es descartado. Por ejemplo, las dos secuencias: int i; float f; int i; float f; son lxicamente equivalentes y el resultado del anlisis son las seis palabras siguientes: int i ; float f ; El carcter ASCII espacio puede formar parte de cadenas literales (alfanumricas), en cuyo caso es protegido del proceso de anlisis, permaneciendo como parte de la cadena. Por ejemplo: char name[] = "Playa Victoria"; es reducido a siete tokens, incluyendo una cadena literal "Playa Victoria" char
8 Anlisis semntico
En lenguajes como el Ensamblador la comprobacin se limita al anlisis anteriormente sealado; con esto se garantiza que el fuente original es correcto (sintcticamente), es decir, es un escrito correcto desde el punto de vista del lenguaje, otra cosa es que tenga un sentido computacional correcto, o diga tonteras, incongruencias o sinsentidos [6]. Por supuesto la meta del compilador es conseguir descubrir con anticipacin (al runtime) el mximo de errores posibles. En los lenguajes de alto nivel, esto se consigue con una cierta comprobacin del "sentido" o "significado" del escrito, es el denominado anlisis semntico (anlisis del significado). La mejor baza de que dispone C++ para esta segunda comprobacin es la comprobacin esttica de tipos ( 2.2). 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 lnea declara que la variable x es tipo int (entero); la segunda declara que la funcin fun devuelve un carcter (char); si una lneas ms adelante se pretende igualar la variable x con el valor devuelto por la funcin, el analizador semntico estara en condiciones de asegurar que existe una incongruencia en las pretensiones del programador, generando el correspondiente mensaje de advertencia o error .
9 Generador de cdigo
Todos estos tokens identificados por el analizador sintctico, son organizados en una estructura como las hojas de un rbol. A continuacin, el generador de cdigo recorre este rbol traduciendo sus hojas directamente en cdigo de la mquina para la que se compila [11]. Si se solicita, el compilador tambin puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspeccin por el programador (este cdigo es tambin dependiente de
la mquina para la que se compila y fcilmente entendible por el humano; puede contener incluso comentarios para facilitar su lectura). Nota: Los compiladores modernos suelen incluir opciones que permiten generar cdigo optimizado para el tipo de procesador que se utilizar. Por ejemplo, el compilador Borland C++ dispone de opciones que permiten generar cdigo optimizado para procesadores Intel de modelos especficos ( 1.4.3a). Como cabra esperar, el compilador GNU c++ es el que ofrece ms 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, despus del generador de cdigo puede ejecutarse un optimizador (peephole optmizer). Este generador de cdigo sera propiamente el compilador, es decir, el encargado de traducir algo entendible por el humano en cdigo mquina. En cualquier caso, el resultado es un fichero "objeto", generalmente con la terminacin .obj o .o. Tambin puede ordenarse al compilador que incluya en el "objeto", determinada informacin adicional que ser utilizada ms tarde por el depurador , por ejemplo los nmeros de lnea de las sentencias. Cuando se hace as, se habla de una compilacin "provisional" o de "depuracin"; distinta de la que se realiza para la versin definitiva (de campo) del programa en la que no se incluyen este tipo de informacin que ya no es necesaria.
10 Enlazado
El ltimo paso en construir un ejecutable es el enlazado. Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 1.4.4). Estos recursos son desde luego los ficheros-objeto obtenidos en la compilacin de los diversos mdulos (ficheros .c) que componen el programa. Adems, si se han utilizado funciones o clases de librera [1] (como es casi seguro), el enlazador ("Linker") es el programa encargado de incluir los mdulos adecuados en el fichero ejecutable final. As pues, la funcin primordial del enlazador es resolver todas las referencias que puedan existir en el programa, es decir: que cada invocacin a un valor o a una funcin corresponda una direccin donde se encuentra el recurso correspondiente, y que estn 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, libreras de enlazado dinmico (en Windows se denominan DLLs). En cuyo caso el enlazador tambin incluir las direcciones y convenciones de llamada adecuadas para que puedan ser trados a ejecucin desde el programa principal. Por ltimo, el enlazador se encarga de insertar en el ejecutable un trozo de cdigo especial: el mdulo inicial, que es el encargado de iniciar la ejecucin ( 1.5).
Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultados:
10.3 Librera
En las pginas siguientes veremos que como resultado de la "compilacin", no siempre se desea conseguir un ejecutable; al menos no en el sentido tradicional del trmino, sino una librera (de las que existen varios tipos), o un fichero objeto.
En lo que respecta al lenguaje C++, existen dos tipos fundamentales: Estticas y Dinmicas. Las primeras son colecciones de ficheros precompilados, cuyo cdigo puede ser aadido a un ejecutable en el proceso de enlazado (los ficheros de la Librera Estndar 5 que acompaan a los compiladores C++ son de este tipo). Las segundas son autnticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecucin. Ms detalles al respecto en: ( 1.4.4a).
11 Errores
La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa. Todos los mdulos involucrados en los pasos anteriores, compilador, analizador sintctico y enlazador pueden detectar errores en nuestro cdigo y mostrar los mensajes correspondientes.
En todos los casos el aviso incluye indicacin del fichero ("fuente" .C/.CPP), el nmero de lnea, y el nombre de la funcin donde se produce el error, as como una explicacin ms 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 crpticos, sobre todo para el profano, pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atencin y entendemos su "porqu". Recordar que todos los compiladores disponen de opciones para modificar el nmero 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 contine hasta que aparezca un nmero determinado de ellos. Respecto a los avisos, puede ordenarse que no muestre ninguno, o que sea ms o menos benevolente en determinados aspectos. Por ejemplo, puede indicarse que la comprobacin siga estrictamente el estndar C++ y que avise de cualquier desviacin al respecto (los compiladores suelen permitir ciertas "peculiaridades" que no son estndar). Nota: La descripcin e informacin acerca del error o advertencia, dependen de la plataforma, pero hemos de sealar 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++ 5.5 es mucho menos riguroso que el producto homlogo de Microsoft, cuyo sistema de verificacin es con mucho superior al del primero, de forma que no es infrecuente que advertencias ms o menos serias e incluso algunos errores advertidos por Visual C++ 6.0 sean totalmente ignorados por Builder. A su vez los errores y advertencias sealados por el compilador GNU Cpp suelen ser ms explicativos que los sealados por Borland o Visual (que en este sentido son ms crpticos).
a un Lvalue ( 2.1), 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 resear aqu, es que las expresiones xxxxx e yyyyy informan sobre el tipo de objeto que hay en cada lado de la expresin de asignacin. Nota: En el captulo dedicado a los tipos de datos ( compilador clasifica los objetos segn su tipo. 2.2) se describe detalladamente como el
En las asignaciones, el Lvalue debe recibir un valor de su mismo tipo. Si el tipo del Rvalue no concuerda con l, el compilador puede intentar adecuarlo, pero si esto no es posible, se produce un error como el sealado. En l se nos indica que el tipo xxxxx, que corresponde al Rvalue (el resultado de la expresin a la derecha del operador = ), no puede ser convertido al tipo yyyyy del Lvalue. Hay que advertir que las expresiones xxxxx e yyyyy estn codificadas. Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++. En concreto, la designacin utilizada en estos mensajes es la misma que utiliza en el operador typeid ( 4.9.14). En situaciones difciles, es mucha la informacin que puede obtenerse de estas expresiones si se observan detenidamente.
Aunque la comprobacin esttica de tipos, y del cumplimiento de las reglas sintcticas realizada por el compilador, resultan muy eficientes en lo que respecta a la deteccin de errores, en realidad, el trabajo dista de ser completo y suficiente. Existen multitud de circunstancias potencialmente errneas que son pasadas por alto. En especial las relacionadas con prdidas de memoria; existencia de punteros descolgados; bucles infinitos; objetos declarados pero no utilizados, y un largo etctera. Algunos de estos errores pueden permanecer agazapados en el cdigo y solo aparecer en circunstancias muy especiales, incluso despus de que la aplicacin haya sido rodada largo tiempo sin contratiempos. Muchas de estas circunstancias pueden evitarse, o al menos mitigarse, siguiendo ciertas pautas y recomendaciones "de buena prctica", muchas de las cuales estn contenidas en la obra TC++PL de Stroustrup; la mayora en forma de advertencias sobre cosas que "no" debe hacerse. Sin embargo, el problema persiste, mxime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arcn, y con el que es posible "volarse la pierna completa". Para reforzar la calidad del cdigo y prevenir errores posteriores (de run-time), se han creado multitud de herramientas. Entre las ms conocidas se encuentran las siguientes: Lint, denominadas as en atencin 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 tambin sirven para "depurar" el cdigo); comprueban la sintaxis y errores en los tipos de datos de forma ms concienzuda y profunda que los compiladores C/C++, y avisan de gran cantidad de peligros potenciales; incorrecciones; desviaciones sobre las reglas universalmente aceptadas como de "buena prctica", etc. Actualmente han llegado a un elevado nivel de sofisticacin, de forma que un buen Lint puede evitarnos muchas horas de depuracin. En realidad es una herramienta que no debera faltar en el taller del programador profesional.
cb. Esta utilidad, originaria del SO AIX, reformatea el cdigo fuente contenido en un fichero y lo vuelca sobre el dispositivo estndar de salida (stdout 5.3) utilizando un formateo basado en sangrados y espaciados, que ayudan a interpretar la estructura del cdigo.
cflow. Esta utilidad, originaria del SO AIX, analiza el contenido de un fichero objeto C/C++ y proporciona en la salida estndar (stdout) un grfico de sus referencias externas. cxref. Esta utilidad, anloga a las anteriores, analiza los fuentes C/C++ y genera una tabla con todos los smbolos encontrados en cada fichero, incluyendo los nombres de los parmetros formales de las funciones (contenidos en la definicin de la funcin). La tabla es mostrada en el dispositivo estndar de salida (stdout), e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definicin est en el cdigo analizado).
Si est interesado en las caractersticas y posibilidades de estos productos, la mayora comerciales y algunos muy costosos, aparte de la correspondiente bsqueda en Google, existe un interesante artculo 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 caractersticas de distintos paquetes, incluyendo una evaluacin de su comportamiento frente a lo que el autor considera deseable. Aparecido en el nmero de Febrero de 1997 del Dr. Dobb's Journal, existe una versin de prepublicacin accesible on-line, que es incluso ms completa que el artculo publicado (probablemente debido a las exigencias de maquetacin de la revista): www.aristeia.com.
Uno de los productos punteros y ms antiguos, es el de Gimpel Software www.gimpel.com; esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint. La primera para Windows, la segunda, ms general, para cualquier entorno que soporte un compilador C, incluyendo Unix y Linux. Si tiene inters en comprobar ms de cerca el tipo de informacin que proporcionan estas utilidades, en el sitio de este fabricante existe una seccin denominada Bug del mes ("Bug of the month") en la que se exponen ejemplos de cdigo, junto con el resultado del anlisis (despus de pulsar un botn). Adems de smamente instructivos, los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto. A mi entender tambin pueden constituir una magnfica fuente de inspiracin para los enseantes que busquen material para ejemplo o evaluacin (sed piadosos en los exmenes porque algunos son realmente para niveles avanzados. No se puede pretender que despus de un semestre de estudio, el alumno est en condiciones de adivinar correctamente el "bug C/C++ del mes" :-)
mdulos son incluidos en durante la fase de enlazado del ejecutable), existen herramientas especficas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias. Estas herramientas realizan su trabajo durante la ejecucin, para lo que modifican el cdigo a analizar incluyendo determinados mdulos que les permiten controlar el desarrollo de la ejecucin (se dice que "instrumentan" el cdigo). La forma de realizar esta "instrumentacin" depende de la herramienta: puede realizarse durante la compilacin ("compile-time"), aadiendo cdigo 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 ejecucin, toman nota de las incidencias, y finalmente proporcionan un informe de las mismas cuando la ejecucin finaliza. Nota: no existe una denominacin unificada para este tipo de productos. Quizs el ms conocido es es BoundsChecker, de Numega www.numega.com (actualmente aparece como Compuware). Tambin puede intentar una bsqueda en Google bajo el epgrafe "Memory debugger".
Despus de todas las medidas preventivas ya reseadas, cuando finalmente, despus 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 diseadores del C++ pensaron que a pesar de la programacin ms 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 especficos se exponen con detalle en el captulo dedicado al Tratamiento de Excepciones ( 1.6).
12 Recursos
Ya hemos sealado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la mquina y Sistema en que deba ejecutarse, y que en el trmino "Compilador" incluimos todas las herramientas auxiliares, enlazador, libreras, etc. Por supuesto que en este sentido, las plataformas comerciales, en especial las versiones denominadas "Enterprise", ofrecen unas prestaciones inigualables, incluyendo potentes depuradores, diseo grfico de elementos con capacidad de arrastrar y soltar ("dragg and drop") elementos, y conjuntos preconstruidos de clases que simplifican extraordinariamente la construccin de determinados aspectos de las aplicaciones. Por ejemplo, el manejo de bases de datos o comunicaciones. En esta categora podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows. En la pgina dedicada a los Compiladores encontrar algunas referencias ( Compiladores).
Si desea saber ms sobre aspectos relacionados con la compilacin, preproceso, anlisis sintctico y semntico, traduccin del cdigo, etc, mi consejo es que consulte "Compiladores y Procesadores de Lenguajes" [Jimnez-04] Inicio.
[1] En el argot de programacin, "funcin de librera" se refiere a un recurso prefabricado; trozos de cdigo, generalmente en forma de funciones o clases que otros han escrito, que incluimos en nuestro programa. La confeccin de programas se parece a la construccin de un edificio en el que cada vez ms se utilizan elementos preconstruidos (algunas veces normalizados), que facilitan y aceleran la construccin. Suelen ser de dos clases: incluidas en el compilador (lenguaje utilizado), que en caso del C++ estn incluidas en la denominada Librera Estndar ( 5), y de terceras partes; libreras especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que adems saben mucho sobre el tema), se han encargado de escribir y comprobar. Por ejemplo: libreras grficas, de comunicaciones, estadsticas, para escribir cdigos de barras en una impresora, Etc. Las modernas "suites" de programacin C++ incluyen completsimas libreras en las que estn resueltas la mayora de las situaciones que habitualmente se suelen presentar en la programacin normal. Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo. El paquete estndar comprende un entorno grfico de programacin (IDE) para Windows, que incluye un potente conjunto de libreras en forma de "herramientas". Es un producto comercial con un precio determinado. En cambio, el compilador, el depurador y la Librera Estndar se suministran gratis. Es decir, se asume que el valor comercial est en el entorno grfico integrado y en las libreras adicionales. [2] Seguramente se me ocurre lo de "cliente" por deformacin 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 ejecucin (tradicionalmente lenta), algunos intrpretes, utilizan en realidad un modelo hbrido. Obtienen un seudo-ejecutable intermedio, mediante un preprocesado seguido de un "parsing", con lo que se obtiene un cdigo "tokenizado" que es el que se entrega realmente al intrprete. [4] A la hora de redactar estas lneas parece estar muy de moda una tcnica denominada Programacin Extrema (eXtreme programming), cuya filosofa se basa en 12 principios o mandamientos, alguno tan pintoresco como el de las "40 horas semanales", segn el cul la mejor manera de aumentar el rendimiento es que los programadores "solo" trabajen 40 horas a la semana, pues est cientficamente demostrado que un trabajador fresco produce cdigo de mejor calidad que uno cansado. A m 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, despus de algunos aos de oficio, los programadores suelen (solemos) ser gente un poco "tocada de la azotea". No cabe duda que pasar aos viviendo en un mundo donde no da igual un punto que una coma en un milln de lneas de cdigo termina imprimiendo carcter. El resultado es que el resto de la gente "normal" no entiende muy bien porqu somos tan maniticos y puntillosos en algunos asuntos, ya que afortunadamente (?), el mundo real suele ser de lgica ms "borrosa" (a veces, tan borrosa que apenas se ve nada...). Nota: Esto de la lgica "Borrosa" viene a cuento y recuerdo de un amigo. Una persona de un gran talento natural que no ha tenido ocasin de recibir formacin acadmica (es mecnico y apenas ha ido a la escuela). En cierta ocasin delante de unas cervezas intent explicarle las diferencias entre la lgica binaria y la difusa
("Fuzzy logic"). Das despus conversaba l con otras personas y me sorprendi como introduca el concepto de la lgica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida. Solo haba cambiado una palabra; "borrosa" en lugar de difusa. [6] Las circunstancias son exactamente idnticas a las que se presentan en los lenguajes naturales. Tambin en estos es posible construir frases sintcticamente correctas pero carentes de sentido (los polticos saben mucho de esto). [7] En esta nomenclatura, una versin 2.4.10 es anterior a la 2.13.0, que a su vez es anterior a la 12.3. [8] Para resolver el problema de que algunos de estos smbolos no aparecen en los teclados de determinados idiomas (por ejemplo, la tilde ~ en los teclados espaoles) se recurri a representarlos mediante ternas de otros caracteres, los denominados trigrafos ( 3.2.3e).
[9] Esta regla de anlisis es conocida como de Max Munch; en realidad no es ningn personaje real, sino un convenio adoptado por los integrantes del primer Comit de Estandarizacin del lenguaje. [10] En general, un "parser" es un programa diseado 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" www.tcl.tk
[12] Como botn de muestra, sealar que en una aplicacin C++ tpica Windows, cuyo ejecutable resultaba de 631 KBytes en su versin "de campo", la inclusin de la informacin necesaria para depuracin hizo aumentar su tamao hasta 3.257 KBytes (Compilador GNU gcc-g++ 3.4.2 para Windows -incluido en Dev-C++ -)
1 Se ejecuta el mdulo inicial. Durante la fase de enlazado de la compilacin, el enlazador aade a cualquier programa C++ un mdulo especial, de inicio, que es realmente el punto de entrada a la ejecucin del programa [2].
Este mdulo realiza diversas tareas, entre ellas iniciar todas las variables estticas o globales (ver nota), controlar la ejecucin de posibles funciones opcionales de inicio (ver punto siguiente) y finalmente, invocar la funcin main ( 4.4.4).
Nota: cuando se compila cualquier mdulo, en el objeto resultante existe un segmento denominado _INIT_ que contiene una referencia ("Init entry") al constructor de cada objeto global que deba ser inicializado, as como un orden de prioridad. Ms tarde, cuando el enlazador construye un ejecutable, estas entradas se agrupan en una tabla, la tabla de inicio ("Init table") que contiene ordenadamente todas las entradas de los constructores de los objetos que existen en los mdulos que componen el programa. Finalmente, esta tabla es utilizada por el mdulo de inicio cuando el programa es iniciado.
2 Se ejecutan las funciones de inicio. Algunos compiladores permiten al programador la opcin de que se invoquen determinadas funciones, antes que se realice la llamada a main. Estas funciones representan tareas preparatorias adicionales, que queremos realizar antes de que se inicie la ejecucin. Esto se consigue con la directiva de inicio #pragma
startup (
4.9.10i).
3 Se invoca la funcin main() Despus de lo anterior, el control pasa a una funcin que debe responder al nombre de main y le pasa algunos argumentos en base a datos que ha recibido a su vez del Sistema Operativo ( 4.4.4). As pues, en ausencia de funciones particulares de inicio, main representa el punto de la ejecucin a partir del cual el programador toma control de la ejecucin. El cuerpo de esta funcin representa la ejecucin del programa, su "carga til".
4 Se ejecutan las funciones de salida. Algunos compiladores permiten la opcin de llamar determinadas funciones antes que se alcance el final del programa, justo antes de su terminacin. Estas funciones, que representan tareas adicionales que queremos realizar antes de que el programa devuelva el control a su entorno de ejecucin. Se establecen con la directiva
#pragma exit (
4.9.10i).
La Librera Estndar C++ tambin proporciona una funcin especial: atexit() que permite la opcin de ejecutar un cdigo especfico en la terminacin ( 1.5.1).
5 Finalizacin
Un programa C++ puede terminar por varios motivos:
Se termine la funcin main(). Bien porque se alcance el corchete de cierre "}", bien porque se encuentra una sentencia return; esto ltimo es lo deseable (aunque no imprescindible), ya que el estndar define que main debe devolver un int a su entorno de ejecucin ( 4.4.4).
Se encuentra una invocacin a la funcin exit(), una funcin de la Librera Estndar ( 1.5.1). Se encuentra una invocacin a la funcin abort(), otra funcin Librera Estndar ( Se lanza una excepcin que no encuentra su manejador ("handler") correspondiente ( 1.6.3 Excepciones imprevistas). 1.5.1).
En el apartado 1.5.1 se incluye la descripcin de algunas de las funciones relativas a la terminacin de un programa [1]. Hay que recordar que en un programa C++ todos los objetos globales se mantienen activos hasta que se han ejecutado todas las funciones de salida. Las variables locales, incluyendo las declaradas en la funcin main son destruidas a medida que quedan fuera de mbito. Al final de un programa C++ Builder el orden de ejecucin es como sigue: Las funciones de salida son ejecutadas en el mismo orden que fueron insertadas por atexit. Las funciones declaradas en #pragma prioridad.
2.2.6.
[1] Aunque en rigor su descripcin debera estar incluida en el captulo 5 dedicado a la Librera Estndar, mientras no implemente completamente dicha parte en el presente "Libro", mantendremos aqu la descripcin de estas funciones. [2] El Estndar indica que tanto este mdulo como el de terminacin son dependientes de la implementacin (pueden ser diferentes para cada compilador).
1 Introduccin
El problema de la seguridad es uno de los clsicos quebraderos de cabeza de la programacin. Los diversos lenguajes han tenido siempre que lidiar con el mismo problema: Qu hacer cuando se presenta una circunstancia verdaderamente imprevista? (por ejemplo un error). El asunto es especialmente importante si se trata de lenguajes para escribir programas de "Misin crtica"; digamos por ejemplo controlar los ordenadores de una central nuclear o de un sistema de control de trfico areo. Antes que nada, digamos que en el lenguaje de los programadores C++ estas "circunstancias imprevistas" reciben el nombre de excepciones, por lo que el sistema que implementa C++ para resolver estos problemas recibe el nombre de manejador de excepciones. As pues, las excepciones son condiciones excepcionales que pueden ocurrir dentro del programa durante su ejecucin. Por ejemplo, que ocurra una divisin por cero, se agote la memoria disponible, Etc. que requieren recursos especiales para su control. En este captulo trataremos del manejador de excepciones C++; una serie de tcnicas que permiten formas normalizadas de manejar los errores, intentando anticiparse a los problemas potenciales previstos e imprevistos. As como permitir al programador reconocerlos, fijar su ubicacin y corregirlos.
Pero que es eso de "lanzar" y "capturar" una excepcin"? En general la frase se usa con un doble sentido: Por un lado es un mecanismo de salto que transfiere la ejecucin desde un punto (que "lanza" la excepcin) a otro dispuesto de antemano para tal fin (que "captura" la excepcin). A este ltimo se le denomina manejador o "handler" de la excepcin. Adems del salto -como un goto-, en el punto de lanzamiento de la excepcin se crea un objeto, a modo de mensajero, que es capturado por el "handler" (como una funcin que recibe un argumento). El objeto puede ser cualquiera, pero lo normal es que pertenezca a una clase especial definida al efecto, que contiene la informacin necesaria para que el receptor sepa qu ha pasado; cual es la naturaleza de la circunstancia excepcional que ha "lanzado" la excepcin [6]. Para las tres etapas anteriores existen tres palabras clave especficas: try, detalle del proceso es como sigue.
throw y catch. El
El juego consiste en indicar al programa que si existe un error durante el "intento", entonces debe lanzar una excepcin y transferir el control de ejecucin al punto donde exista un manejador de excepciones ("handler") que coincida con el tipo lanzado. Si no se produce ninguna excepcin, el programa sigue su curso normal. De lo dicho se deduce inmediatamente que se pueden lanzar excepciones de varios tipos y que pueden existir tambin receptores (manejadores) de varios tipos; incluso manejadores "universales", capaces de hacerse cargo de cualquier tipo de excepcin. A la inversa, puede ocurrir que se lance una excepcin para la que no existe manejador adecuado, en cuyo caso... (la solucin ms adelante). As pues, try es una sentencia que en cierta forma es capaz de especificar el flujo de ejecucin del programa. Un bloque-intento debe ser seguido inmediatamente por el bloque manejador de la excepcin.
El "handler" es el sitio donde continua el programa en caso de que ocurra la circunstancia excepcional (generalmente un error) y donde se decide qu hacer. A este respecto, las estrategias pueden ser muy variadas (no es lo mismo el programa de control de un reactor nuclear que un humilde programa de contabilidad). En ltimo extremo, en caso de errores absolutamente irrecuperables, la opcin adoptada suele consistir en mostrar un mensaje explicando el error. Puede incluir el consabido "Avise al proveedor del programa" o bien generar un fichero texto (por ejemplo: error.txt) con la informacin pertinente, que se guarda en disco con objeto de que pueda ser posteriormente analizado y corregido en sucesivas versiones de la aplicacin [2]. Llegados a este punto debemos recordar que, como veremos en los ejemplos, las excepciones generadas pueden ser de diverso tipo (segn el tipo de error), y que tambin pueden existir diversos manejadores. De hecho se debe incluir el manejador correspondiente a cada excepcin que se pueda generar.
3 Resumen
Hemos dicho que try es una sentencia que en cierta forma es capaz de especificar el flujo de ejecucin del programa; en el fondo el mecanismo de excepciones de C++ funciona como una especie de sentencia if
try { // bloque de cdigo que se intenta ... } catch (...) { // captura de excepciones ... } ... // continua la ejecucin normal
El diseo del mecanismo de excepciones C++, someramente expuesto, tiene la ventaja de permitir resolver una situacin muy frecuente: el bloque en que se detecta el error no sabe que hacer en tal caso (cuando se presenta el error o excepcin); la accin depende en realidad de un nivel anterior, el mdulo que invoc la operacin. Como decimos, esta situacin es muy frecuente ( ), entre otras razones porque si un mdulo pudiera anticipar un error por si mismo, tambin podra evitarlo, con lo que no habra necesidad de mecanismo de excepciones. Esta circunstancia es especialmente patente en el caso de libreras, en las que el autor generalmente no sabe ni puede hacer nada al respecto de ciertos errores a excepcin de informar al usuario. Lo anterior no es bice para que, como buena prctica de programacin, se intente la captura sistemtica de errores lo ms prximo posible a su identificacin, dejando el mecanismo de excepciones para las situaciones realmente imprevisibles. Por ejemplo, siempre que sea posible: if (b == 0) { /* alguna accin... */; } else x = a/b;
4 Precauciones
Cuando se plantean este tipos de cuestiones de seguridad surge inevitablemente una pregunta: Que sucede si se producen errores (circunstancias excepcionales) durante el proceso de control de excepciones?. La respuesta ms honesta es que el sistema perfecto e invulnerable no existe. Aunque el sistema de excepciones de C++ es una formidable herramienta para controlar imprevistos, que permite hasta cierto punto, controlar imprevistos dentro de imprevistos. A pesar de ello, nada puede sustituir a una programacin cuidadosa. El propio Stroustrup advierte: "Aunque las excepciones se pueden usar para sistematizar el manejo de errores, cuando se adopta este esquema, debe prestarse atencin para que cuando se lance una excepcin no cause ms problemas de los que pretende resolver. Es decir, se debe prestar atencin a la seguridad de las excepciones. Curiosamente, las consideraciones sobre seguridad del mecanismo de excepciones conducen frecuentemente a un cdigo ms simple y manejable". Comentarios sobre la idoneidad del mecanismo de excepciones ( 1.6W2).
5 Tipos de excepciones
Durante la ejecucin de un programa pueden existir dos tipos de circunstancias excepcionales: sncronas y asncronas. Las primeras son las que ocurren dentro del programa. Por ejemplo, que se agote la memoria o cualquier otro tipo de error. Son a estas a las que nos hemos estado
refiriendo. En la introduccin (1 ) hemos indicado: "las excepciones son condiciones excepcionales que pueden ocurrir dentro del programa..." y las nicas que se consideran. Las excepciones asncronas son las que tienen su origen fuera del programa, a nivel del Sistema Operativo. Por ejemplo que se pulsen las teclas Ctrl+C. Generalmente las implementaciones C++ solo consideran las excepciones sncronas, de forma que no se pueden capturar con ellas excepciones tales como la pulsacin de una tecla. Dicho con otras palabras: solo pueden manejar las excepciones lanzadas con la sentencia throw. Siguen un modelo denominado de excepciones sncronas con terminacin, lo que significa que una vez que se ha lanzado una excepcin, el control no puede volver al punto que la lanz. Nota: El "handler" no puede devolver el control al punto de origen del error mediante una sentencia return. En este contexto, un return en el bloque catch supone salir de la funcin que contiene dicho bloque.
El sistema Estndar C++ de manejo de excepciones no est diseado para manejar directamente excepciones asncronas, como las interrupciones de teclado, aunque pueden implementarse medidas para su control. Adems las implementaciones ms usuales disponen de recursos para menejar las excepciones del Sistema Operativo. Por ejemplo, C++ Builder dispone de los mecanismos adecuados para manejar excepciones de Windows-32 (asncronas) a travs de su librera VCL [1] ( 1.6w1).
6 Secuencia de ejecucin
Como puede verse, la filosofa C++ respecto al manejo de excepciones no consiste en corregir el error y volver al punto de partida. Por el contrario, cuando se genera una excepcin el control sale del bloque-intento try que lanz la excepcin (incluso de la funcin), y pasa al bloque catch cuyo manejador corresponde con la excepcin lanzada (si es que existe). A su vez el bloque catch puede hacer varias cosas: Relanzar la misma excepcin ( 1.6.1).
Saltar a una etiqueta ( 1.6.2) Terminar su ejecucin normalmente (alcanzar la llave } de cierre).
Si el bloque-catch termina normalmente sin lanzar una nueva excepcin, el control se salta todos los bloques-catch que hubiese a continuacin y sigue despus del ltimo. Puede ocurrir que el bloque-catch lance a su vez una excepcin. Lo que nos conduce a excepciones anidadas. Esto puede ocurrir, por ejemplo, cuando en el proceso de limpieza de pila ("Stack unwinding") que tienen lugar tras una excepcin, un destructor lanza una excepcin .
Como se ver en los ejemplos, adems del manejo y control de errores, las excepciones C++ pueden utilizarse como un mecanismo de return o break multinivel, controlado no por una
circunstancia excepcional, sino como un acto deliberado del programador para controlar el flujo de ejecucin [5]. Ejemplos: ( 4.5.8).
Si ocurren errores durante la construccin de un objeto, los constructores pueden lanzar excepciones [3]. Si un constructor lanza una excepcin, el destructor del objeto no es llamado necesariamente. Cada vez que desde dentro de un bloque-try se lanza una excepcin y el control sale fuera de bloque, tiene lugar un proceso de bsqueda y desmontaje descendente en la pila hasta encontrar el manejador ("Catcher") correspondiente. Durante este proceso, denominado "Stack unwinding", todos los objetos de duracin automtica que se crearon hasta el momento de ocurrir la excepcin, son destruidos de forma controlada mediante llamadas a sus destructores. Si uno de los destructores invocados provoca a su vez una excepcin que no tiene un "handler" adecuado, se produce una llamada a la funcin terminate ( 1.6.3).
Nota: Observe que no se menciona para nada la destruccin de objetos persistentes que se hubiesen creado entre el inicio del bloque try y el punto de lanzamiento de la excepcin. Esto origina una difcil convivencia entre el mecanismo de excepciones y el operador new. Para resolver los problemas potenciales deben adoptarse precauciones especiales ( 4.9.20).
La invocacin a los destructores de los objetos automticos, se realiza solo para aquellos objetos que hubiesen sido construidos totalmente a partir de la entrada en el bloque-intento (objetos cuyos constructores hubiesen finalizado satisfactoriamente). Si los objetos tienen sub-objetos, la invocacin solo se realiza para los destructores de la clase-base. Tema relacionado: Control de recursos ( 4.1.5a)
Nota: En el caso del C++Builder, los destructores son llamados por defecto, pero puede evitarse mediante la opcin -xd- del compilador como se indica a continuacin. Esta opcin, como otras de este tipo, est gobernada por el valor de una constante global ( 1.4.1a).
-x-
-xd
Nota: la eliminacin del mecanismo de excepciones en nuestro cdigo no impide que estas puedan ser utilizadas en aquellas funciones de librera que lo tienen habilitado y sean enlazadas con nuestro ejecutable. Por ejemplo, las rutinas de tiempo real de Borland. Borland C++ Habilita limpieza total. Llamada a los destructores para todos los objetos declarados automticos (locales) entre el mbito del capturador (catch) y el lanzador (throw) de la excepcin cuando es lanzada la excepcin (activo por defecto). Si se activa esta opcin, tambin hay que activar la opcin RT ( 4.9.14).
-xp
Borland C++ Habilita informacin sobre las excepciones. Posibilita identificacin de excepciones en tiempo de ejecucin mediante la inclusin en el objeto del nmero de lneas del cdigo fuente. Esto permite al programa interrogar el fichero y nmero de lnea donde ha ocurrido una excepcin utilizando los identificadores globales __ThrowFileName y __ThrowLineNumber. Deshabilitar el mecanismo de excepciones. Nota: los compiladores gcc deshabilitan esta opcin por defecto para aquellos lenguajes que normalmente no utilizan excepciones (C por ejemplo), pero lo habilitan por defecto para los que, como C++, suelen utilizarlo.
Inicio. [1] Parte de las libreras de C++Builder, la denominadas VCL "Visual Component Library" ( 4.11.8b), han sido desarrolladas en Pascal, y no forman parte de su Librera Estndar C++. Son extensiones particulares de este compilador. [2] Una opcin muy bonita sera que llegado a este punto, el programa pudiera mandar un mensaje e-mail al programador o supervisor avisando del fallo (hoy da esto es trivial desde el punto de vista tcnico). [3] El mecanismo de excepciones fue introducido en C++ en 1989. De hecho, una de las razones de su inclusin fue la dificultad para detectar y controlar los errores ocurridos en los constructores, ya que por definicin estos mtodos no devuelven nada. [5] El Dr. Stroustrup admite que, adems de servir para el control de errores, las excepciones pueden servir como estructura de control en situaciones que no sean necesariamente errneas TC++PL 14.5 "Alternatively, one migth think of the exception-handling mechanisms as simply another control structure". Stroustrup & Ellis: ACRM 15.1 "This design assumes that exceptions are to be used primarily for error handling. Alternative uses, such as loop termination and alternate 'normal' return paths form functions, are clearly possible, but are considered secondary".
[6] Se recomienda utilizar una subclase (definida al efecto) de la superclase exception definida en la librera Estndar ( 1.6.1a).
1 Introduccin
Loque podamos llamar "programacin tradicional", por ejemplo la que se utilizaba (utiliza?) en la confeccin de programas para los primitivos PCs bajo MS-DOS, o en los actuales Win-32 bajo una "ventana" DOS, es un concepto un tanto ambiguo, pero podemos intentar una definicin diciendo que se basa en algunas premisas y caractersticas bastante definidas. Estas caractersticas pueden coexistir juntas o faltar alguna, pero en general se dan simultneamente. En este captulo intentaremos mostrar una visin sinptica de las diferencias entre esta y la programacin "moderna" [1], a la que seguramente tendr que adaptarse el programador C++. Sin embargo, advertiremos desde ahora que la mentada "programacin tradicional" mezcla conceptos distintos e independientes, cuyas diferencias es importante tener claras antes de adentrarnos en la programacin actual. Por ejemplo, la programacin para Windows-32; asunto este que desde luego va ms all que la simple utilizacin de "objetos". Este captulo se ha redactado teniendo en mente la multitud de problemas con que se enfrenta el programador "tradicional" que se ve abocado a trabajar para un SO moderno (Windows inevitablemente?). Intentaremos dentro de lo posible clarificar algunas ideas de ese cmulo de nuevos conceptos que con demasiada frecuencia producen ms de una "indigestin" inicial [2].
2 Sinopsis
Para situarse correctamente en el asunto, es fundamental entender que las diferencias entre la programacin tradicional y la actual tienen su origen inmediato en la evolucin de los Sistemas Operativos, evolucin que ha sido posible a su vez por la evolucin del hardware. Por ejemplo, mquinas capaces de direccionar ms memoria. Tambin por la evolucin de las herramientas de programacin (lenguajes). Las caractersticas y diferencias de la programacin tradicional frente a la actual pueden resumirse en el siguiente cuadro:
Programacin tradicional
Representacin en modo texto Trabajo en mono-programa Trabajo en mono-tarea Ejecucin controlada por el programa Programacin de tipos fijos
Programacin actual
Representacin en modo grfico Trabajo en multi programacin Trabajo en multi-tarea
En el fondo, esta caracterstica es consecuencia de que el programa controla ms o menos directamente sus propios procesos de entrada/salida. Puede por ejemplo "leer" el teclado o "escribir" directamente en el puerto de impresora, por lo que las decisiones pueden tomarse "desde dentro" del programa.
Desde el punto de vista de la interfaz que percibe el usuario, existen dos tipos de aplicaciones: SDI y MDI. SDI significa "Single Document interface". Son aplicaciones que se desarrollan en una sola ventana. Por su parte, MDI ("Multiple Document Interface") supone que la interfaz de la aplicacin es una ventana maestra ("Frame window"), que puede contener mltiples ventanas hijas o "documentos" abiertos simultneamente. Estas ventanas descendientes coinciden con la ventana madre cuando son maximizadas, y se cierran cuando se termina el proceso principal (que abri la ventana maestra).
El usuario puede estar ejecutando diversos programas simultneamente, siendo muy fcil saltar de uno a otro. Por ejemplo, puede estar escribiendo un documento con un procesador de texto y simultneamente, estar consultando ciertos datos que necesita en el Navegador de Internet o en una hoja de clculo. Incluso puede estar ejecutando al mismo tiempo diversas activaciones de un mismo programa. En estas condiciones, cuando ejecutamos nuestro programa, debe compartir recursos con todas las dems aplicaciones en ejecucin. Por ejemplo, nuestras rdenes de impresin no estn ya directamente dirigidas al "puerto" de impresora; en cambio se "lanza" una tarea a un programa (monitor de tareas) que recibe la peticin y la encola en un proceso batch que es el que en realidad gobierna la impresin. Esto hace que en general no sea ya posible utilizar rutinas y operaciones E/S de "bajo nivel", pues estos asuntos son controlados directamente por el Sistema Operativo, todo lo ms que se puede hacer es realizar "peticiones" al sistema de determinados servicios siguiendo las convenciones (a veces muy complejas) establecidas en cada caso. Tenga en cuenta que por ejemplo, en un programa Windows, los datos de la propia ventana en la que corre el programa estn en una zona de memoria gobernada por el Sistema, y que esta informacin queda oculta al programa, que debe limitarse a manejar los mensajes que le llegan desde aquel. Nota: En el captulo dedicado al SO Windows ( 0.7) puede verse un punto de vista complementario, como maneja este Sistema las aplicaciones que corren en l.
La totalidad de los recursos, tales como el procesador, la memoria, los puertos E/S etc. no estn ya a nuestra disposicin. Es el SO el que los controla, procurando que nuestro programa no haga algo equivocado que pueda daar el resto de las aplicaciones. Cuando por error un programa intenta salir del mbito que se le ha asignado (por ejemplo escribiendo en una zona de memoria equivocada), es el SO el que nos alerta. Puede tratarse del clsico mensajito: Este programa ha realizado una operacin no vlida y ser interrumpido. Si el problema persiste consulte con el proveedor del programa (Horror, si soy yo mismo...). Como puede suponerse, las implicaciones para el programador que trabaja sobre uno de estos entornos son enormes, puesto que adems del conocimiento de un lenguaje de programacin adecuado (C++ por ejemplo), se exige el conocimiento de la interfaz; lo que se denomina la API (Application Programmer Interface) del sistema ( 1.7.1). El resultado de que sea el propio SO el que controla las E/S del programa, es que el funcionamiento de este es en realidad un dilogo continuo con el Sistema, del que recibe determinada informacin (entradas), y del que solicita determinados servicios (salidas).
En rigor solo los equipos multiprocesador son capaces de realizar una autntica multitarea; los dotados de un solo procesador son capaces de realizar una suerte de simulacin de tiempo compartido, siempre que el SO y el lenguaje utilizado estn habilitados para ello, aunque desde el punto de vista de la lgica de la aplicacin este detalle sea inapreciable. Aunque el hardware sea adecuado, no todos los Sistemas Operativos son capaces de soportar este tipo de ejecucin. Por ejemplo, Windows 95 solo simula la multitarea, incluso si el hardware es adecuado. Ver algunos comentarios a estos conceptos: Multiprograma & multitarea ( 1.7b).
por el SO. El programa se parece a un bucle que espera continuamente la recepcin de mensajes del Sistema y responde en consecuencia ejecutando determinados procesos. Los procesos pueden incluir peticiones de nueva informacin, o solicitud de determinados servicios. Los mensajes del Sistema tienen su origen en eventos (sucesos) de etiologa muy distinta. Por ejemplo, una interrupcin del teclado; del ratn, que puede hacer clic o doble clic en cualquier rea de la ventana de la aplicacin, o simplemente pasar sobre una zona determinada. Incluso la terminacin del programa ocurre cuando se recibe una peticin del sistema en este sentido (porque se ha hecho clic en el botn de cerrar la aplicacin, o por cualquiera de los otros procedimientos tpicos en las aplicaciones grficas). Ver algunas matizaciones a estos conceptos en "Controlar un programa" ( 1.7a).
las implementaciones introducidas en estos SOs. Actualmente comprende unas 200 clases que encapsulan la prctica totalidad de la API de Windows; adems va ms all de ser una simple coleccin de clases preconstruidas. Constituye en s misma un completo entorno de desarrollo. [7] "Canvas": Espacio grfico que representa un objeto en pantalla. Es una abstraccin utilizada en la programacin de aplicaciones de interfaz grfica (como Windows) que encapsula el contenido del dispositivo grfico. [8] El dibujo ms pequeo que puede representarse en pantalla: un punto. Puede ser monocromo (un color o ausencia de l); de escala de grises, desde el blanco a negro pasando por diversos tonos de gris, o en color. En este ltimo caso el pixel est realmente constituido de tres puntos, cada uno de un color bsico (rojo verde y azul). [9] En los entornos Windows de 16 bits (W-95) quedan vestigios de este funcionamiento cooperativo; son los momentos en que el cursor se transforma en un reloj de arena y no podemos hacer nada hasta que termina cierto proceso. En los entornos Windows de 32 bits, en los que el funcionamiento es preemptivo, sigue saliendo el reloj de arena cuando un proceso est ocupado, pero puede darse foco a otra aplicacin con un clic de ratn.
2 Datos y algoritmos
"Mustreme su cdigo y esconda sus estructuras de datos, y continuar intrigado. Mustreme sus estructuras de datos y generalmente no necesitar ver su cdigo; resultar evidente". Eric S. Raymond "La Catedral y el Bazar" es.wikisource.or En informtica, las ideas-soporte a que aludamos son principalmente de dos tipos: Relativas a la informacin y a su manipulacin (los datos y los algoritmos respectivamente). En lo que concierne a los primeros (los datos), existen multitud de formas de organizarlos; a estas formas las denominamos estructuras de datos. En cuanto a los segundos, existen un nmero casi infinito de algoritmos, pero en lo que aqu nos ocupa, tienen especial importancia los relacionados con el acceso a la informacin, es decir, los relacionados con su almacenamiento y recuperacin. Algoritmos que Shildt denomina mecanismos de datos ( 2). Generalmente se considera que estos mecanismos realizan tres tipos de operaciones: Insercin, borrado y bsqueda de la informacin en la estructura correspondiente. Nota: La denominada STL ("Standar Template Library"), que es parte esencial de la Librera C+ + Estndar ( 5.1) es en realidad un conjunto fascinante de estructuras de datos (aqu llamados contenedores) y de algoritmos para su manejo. Con su ayuda se han construido las aplicaciones ms grandes y exigentes que se hayan utilizado nunca en informtica [5].
Las estructuras y mecanismos de datos han sido muy estudiados; constituyen en s mismos dos mundos dentro de la informtica, y dado que son las herramientas para construir un programa, adems de la experiencia, es conveniente disponer del conjunto ms completo posible de ellas (en este aspecto la programacin se parece al bricolaje). Por ejemplo, si nos referimos a los algoritmos, los mtodos de ordenacin ("Sort") o de construccin de ndices (que viene a ser equivalente), han sido muy estudiados, de forma que se conoce cuales son los ms eficientes para cada caso (algunos incluso patentados). Si el lenguaje no los tiene preconstruidos, tendremos que fabricarlos manualmente con los medios disponibles. En este aspecto, un lenguaje es tanto mejor cuanto ms abstractas sean las herramientas que nos ofrezca (estructuras y mecanismos de datos). Lo que significa que estarn ms cercanas a la idea que tiene en mente el programador-humano y ms alejadas de la forma concreta que adoptarn en la mquina. Este es precisamente el significado de la expresin "Lenguaje de alto o bajo nivel", el mayor o menor grado de proximidad que ofrezcan sus herramientas con las ideas (abstracciones) en la mente humana. Al abordar un problema y decidirse por una estructura o mecanismo de datos concreto, hay un aspecto importante que debe ser conocido y tenido en cuenta por el programador. Es el hecho de que unas estructuras son ms adecuadas para determinados mecanismos que otras. Dicho en otras palabras: las relaciones entre las estructuras de datos y los algoritmos que las manipulan son muy significativas. Por ejemplo: determinadas estructuras son muy adecuadas para operaciones de insercin y recuperacin, de forma que los algoritmos que realizan estas operaciones son muy
simples y rpidos. En cambio estas mismas estructuras pueden ser inadecuadas para buscar informacin en su interior. Resulta por tanto, que la relacin de cada tipo de estructura de datos con los mecanismos bsicos, insercin, borrado y bsqueda, es muy diferente, y debemos pensar detenidamente que relacin tiene nuestra estructura con los mecanismos bsicos (como la usaremos). Tanto las estructuras como los mecanismos de datos son importantes. De hecho, en el diseo de programas caben dos enfoques, segn las consideraciones iniciales consideren prioritarias a unas u otros. En algunos casos la eleccin de la estructura de datos es el primer considerando del diseo, ya que la experiencia ha indicado que el trabajo total de desarrollo y la calidad del resultado dependen grandemente de la idoneidad de las estructuras utilizadas. Una vez elegidas, la eleccin del mecanismo es una consecuencia directa de la decisin anterior. En otros casos la lnea de razonamiento sigue el camino inverso; se deciden las estructuras porque ciertas operaciones crticas utilizan algoritmos que funcionan mejor en esas estructuras. La preponderancia de uno u otro criterio se deja sentir incluso en el diseo de los lenguajes de programacin e incluso de los sistemas operativos [2]. Los lenguajes orientados a objetos (como C+ +) estn diseados alrededor del concepto estructura de los datos, mientras en otros, por ejemplo Lisp, el diseo se centra en el aspecto algortmico. Al tratar de las plantillas ("Templates"), se comenta ms ampliamente la relacin entre datos y algoritmos ( 4.12).
Nota: Tanto en la programacin procedural (tradicional) como en la POO, disear un programa supone construir un modelo. Este modelo goza de la propiedad de ser "ejecutable", mostrando un comportamiento distinto en cada ocasin segn las condiciones de partida o las suministradas durante la ejecucin. El proceso de diseo comienza identificando ciertos elementos que son considerados piezas elementales del modelo, a los que denominamos "Datos". A estos datos se les aade cierta funcionalidad que les es propia. En la POO, este proceso conduce a la definicin de las clases que compondrn el modelo. El resto del diseo consiste en establecer las relaciones de estos elementos individuales entre s, y con respecto a las condiciones de entrada.
En el captulo 5 dedicado a la Librera Estndar, se tratarn estos asuntos de forma ms detallada, concretando cuales son los puntos de vista del C++ y las potentes herramientas que ofrece al respecto; tanto para albergar informacin como para su manipulacin.
nico) o por nombre, para lo que estarn ordenados alfabticamente (construir un ndice con el cdigo de cliente y otro de nombres)...". Si est habituado a la programacin de bases de datos con herramientas de alto nivel, quizs su razonamiento sea el siguiente: "Voy a crear una tabla de clientes donde incluir los datos de cada cliente, comenzando por una columna para el cdigo que ser el ndice principal (ser un INT UNSIGNED). Tambin crear un campo "nombre" que ser un VCHAR NOT NULL UNIQUE...". En uno u otro caso, la estructura (se llame "fichero" o "tabla") es una unidad lgica que se compone una multitud de elementos individuales (se llamen "registros" o "filas" -segn la cultura del programador-). La estructura as concebida tiene un orden, ya que sus elementos estarn conceptualmente uno detrs de otro. Este orden ser numrico, si el acceso se realiza por cdigo de cliente, o alfabtico de nombres si el acceso se realiza por nombre. A su vez, esta estructura lgica se divide an ms finamente: cada elemento se puede considerar dividido en multitud de campos. Aparte de los ya mencionados para cdigo de cliente y nombre, pueden existir muchos mas: direccin, telfono, saldo, clasificacin financiera, fecha ltima compra, vendedor asignado, etc. etc. Por su parte, la estructura fsica corresponde a la forma en que estn contenidos los datos en la mquina, de la que existen dos versiones: una corresponde a la que adoptan los datos en memoria; la otra a su almacenamiento externo (disco). Ambos esquemas son distintos. Resulta evidente que la estructura fsica de datos en los almacenamientos externos no se corresponde exactamente con estructura lgica. En principio, el fichero o tabla de clientes antes mencionado, puede estar representado fsicamente por varios ficheros que pueden ser multivolumen. Es decir: ocupar ms de un volumen lgico ( H8.1.2c1) en la mquina que los alberga. Si son aplicaciones de red, pueden estar incluso en mquinas remotas, distintas de la que ejecuta la aplicacin. Adems, aunque nos figuramos la estructura lgica es un todo continuo (suponemos que despus de un cliente sigue otro), sabemos que la estructura fsica correspondiente, incluso si se trata solo de un fichero, est compuesta por trozos "clusters" que pueden estar dispersos en el disco. La estructura lgica est ordenada (por nmeros o por nombres en nuestro ejemplo). En cambio, la estructura fsica puede estar construida simplemente por el orden "natural" es decir, de creacin de los propios registros. Generalmente, la "apariencia" de ordenacin es el resultado de un proceso complejo que utiliza ndices, tablas y punteros, para proporcionarnos un acceso ordenado a una estructura mucho ms catica. Como queda dicho, los datos son manejados por el programador y el programa (que es la expresin concreta de las ideas de aquel) en trminos de esta estructura lgica. En lo tocante a este aspecto, las herramientas que ofrezca el lenguaje o entorno de programacin, sern de mayor nivel cuanto mayor sea la distancia con que pueda ser manejada la estructura lgica de datos respecto de su verdadera estructura fsica. Precisamente el manejo de tales estructuras ("Databases"), ha originado toda una rama de la industria del software que ha alcanzado un alto nivel de sofisticacin y especializacin. En proyectos grandes es usual manejar los datos a travs de estas herramientas. En estos casos el lenguaje C++ las utilizara a travs de interfaces. Por ejemplo, interfaces con motores relacionales (SQL). Sin embargo, es rara la aplicacin en que el programador no deba manejar uno o varios ficheritos (por ejemplo con parmetros de configuracin), a un nivel "relativamente" bajo, haciendo uso de las herramientas (relativamente simples) que ofrece la Librera Estndar. Tambin es usual que deba manejar, tambin a bajo nivel, alguna estructura de datos en memoria, por
ejemplo una matriz, mediante tcnicas totalmente distintas de las que se utilizaran con un fichero de disco. Como resumen, podemos afirmar que el programador, al menos el programador C++, puede concentrarse en la estructura lgica, pero sin olvidar de vez en cuando mirar la estructura fsica con el rabillo del ojo. Como hemos sealado antes, existen distintos tipos de estructuras de datos (lgicas y fsicas) que se diferencian grandemente en su grado de adecuacin a diversas formas de almacenamiento y recuperacin de la informacin, por lo que es conveniente que el programador tenga ciertas nociones al respecto. Inicio. [1] RAD ("Rapid Application Development") Herramienta de programacin rpida de aplicaciones. Se caracterizan por poseer entornos grficos en los que se dispone de gran cantidad de objetos predefinidos, componentes y controles necesarios para el diseo de las aplicaciones. Estos elementos pueden estar en las denominadas paletas de componentes (Delphi), Caja de herramientas (Visual Basic y Visua C++), etc. Adems permiten la gestin integrada de grandes proyectos software, encargndose de todos los detalles relativos a su construccin (compilacin selectiva, enlazado incremental, etc). Su punto fuerte es poder disear las interfaces (una de las partes ms tediosas de la programacin de aplicaciones) con simples operaciones de arrastrar y soltar. Tambin cuentan con componentes o mdulos que realizan tareas completas, lo que reduce el tiempo que el programador tiene que dedicar a esta parte de la aplicacin. Sin embargo esto tiene su penalizacin o contrapartida, que se manifiesta en un cierto alejamiento del cdigo. [2] La propia Microsoft califica la interfaz de usuario ("Shell") de sus sistemas Windows como de diseo "datacntrico". Es decir, que en vez de estar orientado a las aplicaciones, su diseo se focaliza en los datos y a las operaciones relacionadas con su manipulacin. Como resultado, la interfaz permite al usuario recorrer datos y documentos, incluso editarlos, sin que previamente haya tenido que seleccionar la aplicacin adecuada. La razn aducida es que este diseo, permite al usuario concentrarse en la informacin y en lo que quiere hacer con ella, antes que en las aplicaciones que sern necesarias y en como lo harn. [5] Adems de los recursos de la Librera Estndar, las grandes suites de programacin C++ (Borland y MS por ejemplo) incluyen sus propias herramientas. En especial, MS VC++ dispone de una serie de clases predefinidas en su MFC ("Microsoft Foundation Class -Library-") que permiten manejar fcilmente diversos tipos de estructuras de datos. Algunos programadores las consideran mejores que las correspondientes de STL (es una cuestin de gustos), pero el programador o entidad que deba acometer un proyecto medianamente importante no debe olvidar tres cuestiones: las herramientas de la MFC son exclusivamente para programar en Windows; no son fcilmente portables, y no son estndar.
2. Objetos y algoritmos
"Programmers have very well-honed senses of justice. Code either works, or it doesnt. Theres no sense in arguing whether a bug exists, since you can test the code and find out. The world of programming is very just and very strictly ordered
and a heck of a lot of people go into programming in the first place because they prefer to spend their time in a just, orderly place, a strict meritocracy where you can win any debate simply by being right". Joel Spolsky en "A Field Guide to Developers" www.joelonsoftware.com.
1 Sinopsis
Sin pretender ser demasiado rigurosos y en un sentido amplio del trmino, podemos decir que un programa tiene dos tipos de componentes: datos e instrucciones [1]. Los primeros representan el objeto pasivo de las transformaciones y manipulaciones que tienen lugar en la mquina. Los segundos representan las frmulas o recetas que definen como debe efectuarse la manipulacin. Para aclarar estos conceptos, quizs mejor que mis palabras sean las de Alexander Stepanov, creador de la Librera Estndar de Plantillas C++: "Things that have state and change their state are objects (datos). And then there are things that are not objects. A binary search is not an object. It is an algorithm" [3]. Aunque ambos conceptos son suficientemente simples e intuitivos como para no necesitar definicin, incluiremos algunas consideraciones adicionales al respecto. Debemos sealar tambin que este, como casi todos los criterios de clasificacin, incluye una dosis considerable de arbitrariedad. Aunque en la programacin tradicional (procedural 1.7) suele existir una clara diferenciacin entre los elementos pasivos del programa (datos), y los activos (algoritmos), que se agrupan en funciones, procedimientos -o bajo cualquier otro nombre-, existen circunstancias en las que los algoritmos pueden constituir la materia prima (datos) de otros algoritmos. Es el caso por ejemplo, de lenguajes que permiten escribir programas que sirven para manipular otros programas (intrpretes y compiladores).
2 Datos
Algo que contiene informacin que no sea informacin sobre clasificacin o computacin (tambin denominados objetos); normalmente en forma de patrones de bits alojados en memora. Una caracterstica fundamental de los datos es que se puede afirmar de ellos que tienen un "valor" [2]. Los datos pueden tener muchas propiedades o atributos, pero una de las ms importantes es su capacidad de cambiar el "valor". Denominndose constantes ( "valor" pueda ser modificado o no a lo largo del programa. 3.2.3) y variables, segn que su
Cuando en esta publicacin queramos referirnos a estos componentes "datos" (constantes y variables) utilizaremos el trmino objeto-dato para distinguirlos de los "objetos" a secas (instancias de las clases 4.11.5).
3 Instrucciones
Tambin llamadas algoritmos. Informacin que se refiere a manipulaciones de los datos y/o los dispositivos fsicos del sistema (ordenador) que soporta el programa. Tambin adoptan la forma de patrones de bits alojados en memoria. Nota: Precisamente, esta caracterstica de que las instrucciones estn alojadas en la memoria de la propia mquina es lo que caracteriza a los ordenadores modernos como mquinas Von
Neumann. Esto que hoy se nos antoja natural (como la cada de manzanas antes de Newton), supuso un salto conceptual importante en la ciencia informtica, ya que en los primitivos ordenadores (mejor diramos "mquinas"), los datos y las instrucciones eran tratados de forma diferente. A veces el "programa" estaba tan ntimamente relacionado con la mquina que cambiar de "programa" supona recablear el dispositivo si era elctrico, o cambiar piezas si era mecnico. Al tratar de la Estructura de la informacin ( 1.8), nos hemos referido a datos y algoritmos. En el
epgrafe dedicado a la Librera Estndar de Plantillas STL ( 5.1), volveremos a encontrarnos con ellos, y veremos una forma muy general de tratarlos bajo la denominacin de contenedores (estructuras algebraicas que contienen datos) y algoritmos, unos operadores genricos que actan sobre ellas. 3.1 Como se ha sealado (Introduccin a la POO 1.1), precisamente uno de los paradigmas de la Programacin Orientada a Objetos es el encapsulamiento de datos e instrucciones en entidades a las que, de forma genrica, denominamos objetos. En este sentido, un objeto es una regin especfica de memoria que puede contener un conjunto de datos e instrucciones sobre su manipulacin. 3.2 En C clsico, las variables deben ser declaradas al principio de las funciones y antes que cualquier sentencia ejecutable, por el contrario, en C++ pueden ser declaradas en cualquier punto. A este tipo de declaraciones se las denomina de referencia, e introducen uno o ms identificadores en un programa, asocindolos con un tipo de variable. Ejemplos: int x, y; char c; short corto; long distancia; int * ptr;
4.1.2)
[1] El en un sentido estricto, el "programa" solo contiene instrucciones; aunque desde luego pueden existir mltiples puntos de vista. Por ejemplo, para Stroustrup y Ellis un programa es mramente uno o ms ficheros enlazados juntos, y un fichero consiste en una secuencia de declaraciones" ( [2] Formalmente denominado Rvalue ( 2.1) 1.3.1)
[3] Al Stevens: "Entrevista a Alexander Stepanov" Dr. Dobbs's Journal. Marzo 1995.
1 Sinopsis
Hemos sealado que, en un sentido amplio, un programa tiene dos tipos de entidades: datos e instrucciones, y que a su vez, los datos pueden ser constantes y variables. Una caracterstica importante de los datos (en especial los variables) es que pueden tener varios atributos, estos atributos o propiedades pueden ser relativas al tiempo de compilacin y/o al tiempo de ejecucin (runtime). En Declaraciones ( 4.1) se exponen estos conceptos de forma ms general. Por ahora consideremos que el objeto-dato puede tener los siguientes atributos: Identificador Tipo de dato Clase de almacenamiento Enlazado Direccin (Lvalue Valor (Rvalue ) )
Nota: estos atributos no son exclusiva de los objetos; las funciones (algoritmos) tambin tienen los atributos identificador, tipo , enlazado, direccin y valor (el que devuelven en su caso).
2 Identificador
El identificador es el nombre con el que el programador reconoce un objeto-dato especfico, constante o variable [3] ( 3.2.2 Identificadores). En la prctica, el identificador puede ser un simple nombre o una expresin que represente unvocamente al objeto (un objeto se puede conocer por su direccin, sin que se sepa o preocupe su nombre). Ejemplo: int x = 5; x es el identificador de un miembro de la clase de los enteros de valor 5. char* ptr = "String"; ptres el identificador de un miembro de la clase de los punteros-a-carcter. Apunta a una constante de cadena de la que no conocemos su nombre, solo su direccin.
3 Tipo
El tipo (tambin conocido como tipo de dato) define cuanta memoria es necesaria para almacenar el objeto, como se interpreta el datagrama de bits que hay en el lugar de almacenamiento del objeto; que rango de valores son posibles, y que operaciones les son permitidas a los objetos de dicho tipo.
El concepto tipo de dato tiene una importancia capital en el mbito de la programacin y es la piedra angular sobre la que est construido el propio lenguaje C++ [1]. Es pues de suma importancia asimilar ntimamente el significado de este concepto para comprender y utilizar C++ con un mnimo de soltura. Cada tipo de dato tiene un sentido particular para el compilador (y para e programador). El tipo puede considerarse como un conjunto de propiedades (dependiente a veces de la implementacin) que, junto con un conjunto de operaciones que les son permitidas y el rango de valores posibles, es asumido por los miembros de dicho tipo. Como se ver ms adelante, el compilador C++ deduce este atributo a partir del cdigo; bien de forma implcita, bien mediante declaraciones explcitas [4]. En C++ existen dos clases de tipos: los definidos intrnsecamente en el lenguaje (tipos preconstruidos en el lenguaje, fundamentales o bsicos), y los definidos por el usuario (tambin llamados abstractos). Precisamente esta capacidad de permitir al usuario "inventar" nuevos tipos a la medida de sus necesidades, es una de las caractersticas del lenguaje. En cuanto a los primeros, se suponen 5 tipos bsicos y muchos ms agregados. En realidad, los tipos constituyen en una estructura muy compleja que incluye 4 categoras bsicas con varias subcategoras ( datos). 2.2 Tipos de
En mi opinin, nunca se insistir bastante en la importancia fundamental de entender bien el concepto tipo de dato en el estudio del C++; aparecer con frecuencia en muchas definiciones y explicaciones. De hecho, gran parte de la estructura del propio lenguaje y del sistema de seguridad y comprobacin del compilador gravitan sobre este concepto. Representa algo as como el "Who is who" de las entidades del universo C++ (por lo dems, una sociedad muy "clasista"). Nota: conviene recordar que C++ dispone de dos operadores especficos que permiten obtener informacin sobre los tipos en tiempo de ejecucin: sizeof ( 4.9.13), que permite averiguar 4.9.14), el tamao en bytes de cualquier tipo estndar o definido por el usuario, y typeid ( con el que pueden obtenerse algunos datos adicionales.
4 Clase
La clase de almacenamiento ("storage class"), determina donde se guarda la informacin; su duracin (por cuanto tiempo), que puede ser toda la vida del programa o solo durante la ejecucin de ciertos bloques de cdigo, y algunos aspectos de la visibilidad y el mbito. Situacin; es el sitio donde se aloja el dato (constante o variable). Este atributo es significativo porque el programa dispone de varios sitios distintos donde guardar los objetos; sitio que se elige en funcin de ciertas caractersticas del objeto ( 1.3.2) Duracin ( 4.1.5 "Lifetime") es el periodo durante el que la variable tiene existencia real (datos fsicamente alojados en memoria). Es un atributo de tiempo de ejecucin. mbito ( 4.1.3), tambin llamado campo de accin o mbito lxico ("Lexical scope") es la parte del programa en que un objeto es conocido por el compilador. Es una propiedad de tiempo de compilacin. Visibilidad ( 4.1.4 ) es la regin de cdigo fuente desde la que se puede acceder a la informacin asociada a un objeto.
La clase de almacenamiento puede ser definida de forma explcita o implcita ( Especificadores de clase de almacenamiento).
4.1.8
5 Enlazado
Como se ha indicado ( 1.4), enlazado es el proceso de creacin de un programa que sigue a la compilacin. Permite que a cada instancia de un identificador sea asociada correctamente con una funcin u objeto particular. Cada objeto tiene un tipo de enlazado que puede ser de dos clases: esttico y dinmico. A su vez, cada objeto tiene adems un atributo de enlazado; atributo que est estrechamente relacionado con el mbito, y que puede ser de tres clases: externo, interno y sin enlazado ( 1.4.4).
6 Direccin (Lvalue)
La direccin, localizacin, localizador o Lvalue del objeto-dato es una direccin de memoria donde comienza el almacenamiento. Puede ser expresada directamente por un valor (que represente una direccin de memoria en la arquitectura de la computadora utilizada) o una constante, variable, o expresin que pueda traducirse en una direccin. Cuando queramos referirnos especficamente a la direccin de un objeto-dato de nombre x utilizaremos la expresin Lvalue(x), aunque ms adelante veremos que C++ tienen su forma especfica para referirse a ella. El nombre viene histricamente de left value valor a la izquierda, en referencia a que legalmente puede estar a la izquierda (el extremo receptor) en una expresin de asignacin ( 4.9.2). Es decir, el miembro que "recibe" el valor involucrado en la asignacin. Esto tiene sentido porque en C++ una expresin del tipo x = 3; que definiramos coloquialmente como: hacer el valor de x igual a tres, puede enunciarse ms formalmente diciendo: poner un 3 en la direccin de memoria sealada por x, lo que tambin podramos expresar abreviadamente como [2]: Lvalue(x) 3 El Lvalue de un objeto puede ser fijo (constante) o variable. Un Lvalue modificable significa que la direccin puede ser accedida y su contenido legalmente modificado. Por ejemplo: x = 4; es una expresin vlida si x es una variable de tipo entero; en su direccin puede ponerse un patrn de bits que significar un valor 4 para el compilador (precisamente porque asume que ah se aloja un int). En otro caso el mismo patrn de bits puede significar algo muy distinto. Un Lvalue constante significa lo contrario, por ejemplo, la expresin 4 = x no es correcta porque el Lvalue de 4 no es modificable. La expresin a+b = 4 tampoco es correcta, porque a+b no tiene Lvalue (no es un "objeto", no puede interpretarse como una direccin de memoria). El Lvalue de las variables estticas se asigna en tiempo de compilacin, tienen una direccin fija y conocida desde el principio en una zona de memoria especial reservada para las variables estticas y globales ( 1.3.2).
En las variables automticas (dinmicas) el Lvalue se asigna en tiempo de ejecucin, la direccin (y por supuesto el valor) se conocen solamente durante la ejecucin del bloque de cdigo correspondiente. Ocurre incluso, que cuando una funcin es llamada recursivamente, para cada activacin de la misma se crean distintos Lvalues para el mismo nombre.
7 Valor (Rvalue)
El Rvalue es la interpretacin que hace el programa del patrn de bits alojado en la direccin asignada al objeto-dato. Histricamente Rvalue es la abreviatura del ingls right value, valor a la derecha, en referencia a los valores que legalmente pueden estar a la derecha (extremo emisor) en una expresin de asignacin. Un Rvalue es una constante, variable, o expresin que pueda traducirse en un valor. Por ejemplo 4 + 3 es un Rvalue. Cuando queramos referirnos especficamente al Rvalue de un objeto de nombre x lo expresaremos: Rvalue(x). Las variables que no son constantes pueden modificar su Rvalue a lo largo del programa. Una expresin del tipo x = a; coloquialmente: hacer el valor de la variable x igual al valor de la variable (o constante) a, puede enunciarse ms formalmente: copiar el Rvalue de la variable cuyo nemnico es a en la direccin de memoria (Lvalue) de la variable cuyo nemnico es x, lo que podramos expresar con: Lvalue(x) Rvalue(a)
pnt
Nemnico que identifica una variable; suponemos que esta variable es de tipo puntero, y que en este caso apunta a una variable que llamaremos x. Entonces, por definicin de puntero: Rvalue(pnt) == Lvalue(x)
*pnt
El asterisco * es el operador de indireccin ( 4.9.11); el resultado de aplicarlo a un puntero es el objeto sealado por el puntero. En este caso sera el objeto apuntado por pnt; es decir: *pnt == x. La expresin *pnt solo tiene sentido si el Rvalue(pnt) == Lvalue(x), en otras palabras: Si el valor de pnt es la direccin de almacenamiento de un objeto, o lo que es lo mismo, si pnt es un puntero.
Debe tenerse en cuenta, que *pnt devuelve el objeto apuntado por pnt a todos los efectos. Es decir, es un objeto con Rvalue y Lvalue, por lo que las dos expresiones de asignacin siguientes tienen sentido: X = *pnt; *pnt = Y; //equivale a: X = x // equivale a: x = Y
&pnt
& es el operador de referencia ( 4.9.11); al aplicarlo a una variable, da como resultado la direccin (Lvalue) de la variable. En este caso sera la direccin de pnt, es decir: &punt es sinnimo de Lvalue(pnt). Esta expresin siempre tiene sentido si pnt es un objeto vlido, ya que por definicin, cualquier objeto tiene un almacenamiento. A la luz de lo dicho, es evidente que: Rvalue(pnt) == &x Precisamente la asignacin de un puntero es una expresin del tipo: int* pnt = &x; en este caso, int* pnt indica que pnt es un puntero-a-entero; despus se le asigna la direccin de la variable x (se asume por tanto que x es de tipo int). A partir de este momento se dice que pnt apunta o seala a x. Cuando * y & se utilizan en esta forma se denominan operadores de puntero. Tngase en cuenta, que el asterisco *, adems de ser el operador de indireccin, tambin puede ser especificador de tipo (de tipo puntero 4.2.1a) y operador de multiplicacin ( 4.9.1). Por su parte, & adems de 4.9.3). operador de referencia, tambin puede ser el operador AND en operaciones de bits (
Nota: Consecuencia inmediata es deducir que en C++ hay casos en que diferentes operadores comparten el mismo identificador. Podemos decir entonces que algunos operadores C++ estn sobrecargados ya de origen. Precisamente el compilador distingue de que operador concreto se trata en cada caso, por el tipo y nmero de los operandos involucrados. Ms informacin al respecto en Inicio. [1] C++, al igual que muchos de los actuales lenguajes de programacin "orientados a objetos", obedecen a un diseo centrado principalmente en el "dato", aunque tambin existen lenguajes en los que se pone mayor nfasis en el algoritmo. [2] Utilizamos el smbolo para indicar una asignacin de derecha a izquierda (en C++ el smbolo del operador de asignacin simple es = 4.9.2); utilizaremos == como indicador de igualdad (este si es el smbolo C++ del operador relacional "igual que" 4.9.12). Finalmente utilizaremos el smbolo para sealar que lo que sigue se deduce o es "consecuencia de" lo anterior (smbolo de inferencia). 4.9 Operadores.
[3] El identificador no es solo privativo de los datos, tambin las instrucciones pueden tener un identificador. Por ejemplo, las funciones y los operadores. En el caso de las funciones el identificador se dice que es el "nombre" de la funcin; en el caso de los operadores, el identificador se dice que es el "smbolo" del operador. [4] El tipo de dato en los lenguajes de programacin se corresponde con el concepto matemtico de "dominio". Ms concretamente, en la teora de conjuntos.
interpretacin del tipo de objeto viene determinada por el contexto (expresin utilizada para acceder al objeto). Por ejemplo, en la expresin float y = 10.0/3; el valor 10.0/3 es interpretado por el compilador como un double, que posteriormente ser sometido a una conversin estrechante para convertirlo en un float. Segn la forma en que los lenguajes se comportan frente a los individuos de las diversas "castas", se clasifican de dos grupos: fuerte y dbilmente tipados. Como puede suponerse, los primeros son ms estrictos e intolerantes que lo segundos frente a la promiscuidad entre tipos [2], aunque caben todas las posturas intermedias. En los primeros (lenguajes fuertemente tipados) como C/C++, la tcnica consiste en que el tipo de objeto queda definido desde el principio de su existencia (por declaracin formal o por el contexto). A partir de aqu, quedan perfectamente establecidas las posibilidades del objeto, y estas posibilidades se utilizan como mecanismo de seguridad. Por ejemplo, si en la declaracin anterior, la variable y, que es un float, se utiliza como argumento de una funcin que espera un char, el compilador avisar con un mensaje de error. En el extremo opuesto estn otros lenguajes, tpicamente los denominados "dinmicos" (de tipo script) como JavaScript o Tcl, en los que el tipo de objeto no est completamente definido desde el principio. Es justamente su utilizacin posterior la que establece sus caractersticas. En estos lenguajes es posible establecer expresiones del tipo var z; (z es una variable sin ms indicacin de sus propiedades). Posteriormente es posible hacer z = 10 o z = "ABCD". Ser justamente la asignacin la que complete las caractersticas de la variable que se dejaron indeterminadas. C++ es un lenguaje fuertemente tipado desde el punto de vista esttico ("Strong static type checking"). Es decir, en tiempo de compilacin queda perfectamente definido el tipo de los objetos, y puede advertirnos de cualquier veleidad o error al respecto de tomar un tipo por otro o utilizarlo de forma inadecuada. Sin embargo, en tiempo de ejecucin se comporta a veces de forma muy permisiva porque el compilador proporciona algunas conversiones automticas de tipo (ver a continuacin). Tambin es posible que estas conversiones sean forzadas de forma explcita en el cdigo (en realidad el programador puede terminar haciendo casi lo que le venga en gana).
Nota: La razn de que se haya puesto especial nfasis en la comprobacin esttica de tipos (en tiempo de compilacin) en detrimento de la comprobacin dinmica (en tiempo de ejecucin), se debe a que en C++ todas las premisas de diseo han estado encaminadas en favor de lograr la mxima velocidad de ejecucin.
3 Conversin de tipos
Al llegar a este punto, conviene hacer una advertencia: a veces es necesario y conveniente que el programa permita un poco de "manga ancha" en la cuestin de los tipos. En el caso de C++ esto puede ocurrir de dos formas: Transformaciones realizadas espontneamente por el compilador . .
son perfectamente legales en C++, aunque la segunda sea desde luego bastante escandalosa desde el punto de vista formal. Esta posibilidad de transformacin, realizada muchas veces de forma automtica por el compilador, y que a la postre se traduce en una cierta "promiscuidad" con los tipos de datos, es precisamente uno de los reproches que le hacen a C++ sus detractores. En este sentido C++ es un lenguaje dbilmente tipado. En el apartado de Conversiones estndar ( 2.2.5) se incluye una continuacin de esta "cuestin de los tipos" desde el punto de vista de las conversiones que realiza el compilador de forma rutinaria. Es importante tener conciencia de esta ambigedad con que se comportan algunos tipos de datos en determinadas circunstancias. Como hemos visto en el ejemplo, un char puede ser en un momento un carcter, para a continuacin comportarse como un int, sin dejar por ello de seguir siendo un autntico char. Otro ejemplos (de los varios que se podran citar) de conversin automtica de tipos realizada por el compilador ocurre con los tipos bool ( 3.2.1b), y la realizada en la invocacin de 4.4.6) funciones para ajustar el tipo de los parmetros actuales con los formales (
El tipo dinmico de una expresin que es un Lvalue, es el tipo del objeto ms derivado a que se refiera la expresin (esto solo tiene sentido en jerarquas de clases). Ejemplo: Supongamos que [4]: B* p; S s; p = &s; // p es puntero-a-superclase B // s es objeto de subclase S derivada de B // Ok p seala a s
En este caso decimos que el tipo esttico de p es B* (puntero-a-superclase B), y que el tipo dinmico de la expresin *p (que es un Lvalue), es S. Inicio. [1] C++ es un lenguaje de propsito general que no ha sido especialmente diseado para la computacin numrica, por lo que de forma nativa no dispone de tipos de datos de alto nivel, ni por consiguiente, de sus operaciones. Sin embargo, su velocidad de ejecucin lo hace muy dotado para todo tipo de aplicaciones de clculo, adems dispone de recursos muy potentes al respecto en su Librera Estndar ( 5).
[2] El tratamiento que hacen de los "Tipos" los diferentes lenguajes si es muy variado. Frente a los fuertemente tipados, como C/C++, existen otros prcticamente sin tipo definido ("Tipeless"), mientras que otro grupo presenta una posicin intermedia con una tipologa muy simple y permisiva ("Loosely typed"). Un caso extremo est representado por BCPL ( 0.Iw2), uno de los ancestros de C, y una posicin intermedia estara representada por JavaScript, que cuenta solo con cinco tipos distintos y una gran capacidad de adaptacin automtica entre ellos. En este punto cabe hacer otra observacin; en atencin a su capacidad de adaptacin, ms que lenguajes sin tipo ("Tipeless"), algunos autores prefieren decir que se trata de lenguajes con tipos dinmicos o tolerantes ("Dynamic types" o "Tolerant types"). [3] Ms detalles respecto a estos constructores para los tipos bsicos en el captulo dedicado al operador new ( 4.9.20).
[4] Para comprender cabalmente el ejemplo debe consultarse el epgrafe Punteros en jerarquas de clases ( 4.11.2b1).