El lenguaje "C" y sus compiladores para Sinclair QL

Ignacio Enrique
Valladolid, diciembre 1988

En éstas líneas me propongo describir brevemente el lenguaje "C", sus posibilidades (a muy grandes rasgos) y matizar brevemente las posibilidades pros y contras de los tres compiladores de "C" para sistema QDOS que hay actualmente disponibles.

Cuando en la década de los 70 se definió el lenguaje "C" por Kernighan y Ritchie y Thompson diseñó el UNIX, el mundo de la informática poco a poco se contagió de una rara enfermedad que hoy podríamos llamar UNIXMANIA, yo la llamaría enfermedad, enfermedad en el sentido de que deja alucinados a sus usuarios y que supone una especie de histeria colectiva dentro del mundo de la informática. Desde 1985 en que más o menos intento enterarme de lo que anda por este mundillo, llevo oídas muchísimas cosas respecto del UNIX y del C incluso he leído publicaciones al respecto y he seguido las apariciones de los primeros ordenadores personales con sistema UNIX. Después de ello, y de los ríos de tinta respecto a si "tenemos aquí al nuevo estándar de los sistemas operativos de 16, 32 bit..., la revolución de la informática..." uno ve las cosas de un modo un tanto escéptico, no así respecto al lenguaje "C", pese a que se dice que el UNIX y el "C" son una especie de amigos inseparables. El sistema operativo UNIX dentro de los ordenadores personales parece que está en una especie de compás de espera (no así dentro de los miniordenadores), ya veremos que es lo que ocurre con él. Lo que si es cierto es que la filosofía del UNIX subyace en los nuevos sistemas operativos multitarea que han aparecido en los 80 y entre ellos nuestro QDOS, sistemas que huyen de las estructuras rígidas de sistemas como el CP/M o el MS/DOS y ahora el OS/2 (multitarea no tan multitarea).

Ordenadores personales que trabajen con UNIX aparecieron en el 86 el Triple XXX, el ATT UNIX-PC, el SORD 680 UX y... pocos más (Los nombrados, todos se basan en la familia de CPU MC68000, que curioso...), los ordenadores en 1987 se vieron en una fase de shock ante el abandono de IBM del PC como tal y el anuncio de la nueva serie (que no introduce grandes transformaciones) y se abrió un compás de espera respecto a los nuevos ordenadores personales de 32 bits, las cosas hoy en día siguen bastante revueltas pero en ése revoltijo el UNIX no aparece por ningún lado de un modo claro, encima ahora sale una nueva moda en cuanto a las CPU de tecnología RISC que parece que puede re-revolucionar el mundo de la informática (personalmente creo que la informática de gestión que no precisa para nada de las instrucciones complicadas de las CPUs se va a ver muy favorecida por éstas nuevas CPU, no así la informática científica y de diseño que seguirá precisando de instrucciones complicadas) y de hecho el Archímedes de Acorn en Inglaterra es un ejemplo excepcional asombroso en muchos de sus aspectos y el Transputer que parece que cada vez se va a aplicar a más placas base tiene grandes expectativas.

Pero de todo este revuelo hay un ente que se está fortaleciendo en todos los frentes y éste es el lenguaje "C". La razón es muy sencilla: llega hasta unos niveles de operatividad muy altos dejando en todo momento la posibilidad de independizarse del sistema operativo en que corra, lo cual permite una portabilidad de programas muy generalizada, incluso hay compiladores de "C" como el Lattice que dispone de versiones para prácticamente todos los ordenadores personales del mercado (incluido el QL). Esta portabilidad no cabe duda que es el mejor arma ante un mercado de Hardware en caos.

¿Que tiene el lenguaje C, que no tengan los demás? una sola cosa: sencillez

Esta sencillez es la clave de su éxito y de su portabilidad (algo parecido de lo que puede ocurrir con las CPU RISC). En C se juega con muy pocos elementos algunos casi a nivel de ensamblador y otra cosa, libertad prácticamente absoluta. Hay muy pocas cosas que no se puedan hacer en "C" de un modo eficiente.

Las poquitas cosas que tiene el C son las siguientes:

Tipos de dato: char, short, int, long, float y double

Operadores: aritméticos (+.-,*,/,%), relacionales (>,>=,<,<=,==,!=), lógicos(&&,||,!), de manejo de bit(&,|,^,<<,>>), de asignación (=,<op>=,++,--), condicionales (?:)y de acceso a datos(*,&,[],,,->)

Estructuras de control: sentencias y expresiones, bloques, sentencia if-else, sentencia switch, bucles (for, while y do), saltos y etiquetas (goto, break, continue)

Matrices, punteros, estructuras y uniones

Con todos éstos elementos se crean funciones y con grupos de funciones se crean programas, programas que arrancan en una función de nombre "main".

Aunque alguno se piense que me he olvidado de algo, he de decirle que no, en esas 7 líneas está todo lo que reconoce un compilador de "C", aunque a ello hay que añadir el preprocesador de macros, que permite trabajar con macros del mismo modo que en un macroensamblador. Pero ¿Dónde están las instrucciones de entrada-salida, de manejo de memoria, de...?: en las librerías de funciones, y es con las funciones con lo que logra el "C" su posible utilidad para todo. Así pues, la gran potencia del "C" estriba, en su coerción aritmética, en la gran variedad de sus operadores, en el manejo de estructuras, uniones y punteros y en su macroprocesador, además el lenguaje se enriquece de un modo natural mediante funciones. La gran cantidad de operadores muchos de ellos unarios puede hacer que al leer un lenguaje en C nos quedemos perplejos de la cantidad de cosas que se pueden hacer con cuatro líneas de código. Además en general, cuanto más compacto sea el código, más rápido es éste ( y más difícil de comprender...), aunque siempre podemos escribir los programas de un modo claro aunque el código no sea tan rápido. El otro pilar de la potencia del C es su absoluta libertad de hacer cualquier cosa, libertad que nos puede llevar a hacer grandes burradas que el compilador difícilmente detectará dado que la detección de errores en las funciones queda siempre bajo la responsabilidad del programador.

De todos modos no nos asustemos ante el "C", no es tan fiero como lo pintan, y si no, no hay más que comprobarlo con alguno de los compiladores de C de que disponemos con el QL.

Mi llegada al mundo del "C" ha sido una de las más raras que uno pueda haberse imaginado. Ha sido un lenguaje al que he llegado de rebote pero del que poco a poco estoy descubriendo posibilidades insospechadas. Al principio no me gustaba casi nada "Donde esté el SuperBASIC y un buen compilador... o un ensamblador para hacer procedimientos...", sí, esto es cierto pero llegas a un punto donde necesitas hacer algo en ensamblador, que te gustaría tener algo que te hiciera de intérprete de flujos propios de un lenguaje de alto nivel. En éste punto pocos lenguajes hay que te lo puedan hacer de modo eficiente, uno de ellos es el "C" (el otro podría ser el FORTH, pero éste con su sintaxis tan súper orientada a trabajar con una pila puede resultar un poco arisco (aunque el intérprete es genial para depurar (pero con un MC68000 se pueden llevar más cosas que una sola pila, como en cualquier CPU que funcione con el esquema IN/OUT (Z80, 8080, 8086, 80286, 80386, 6502...), desaprovechándose en parte la potencia de la CPU))),(Perdonad si me pierdo en los paréntesis). Digamos que tenemos dos lenguajes de relativo bajo nivel óptimos para aprovechar los recursos de cualquier máquina uno, el FORTH, además con la facilidad de un intérprete pero el otro, el "C", con una sintaxis más intuitiva y natural desde el punto de vista humano (aunque todo es acostumbrarse a la dichosa notación polaca inversa para el FORTH).

El primer compilador que tuve ocasión de ver fue el de GST, de éste a grandes rasgos me desagradó de sobremanera el que no dispusiera de estructuras ni de uniones ni de números de coma flotante, después he tenido acceso al de Metacomco y de momento creía tener delante a un C prácticamente estándar al que no le faltaba de nada. El de digital parece que según la publicidad iba a ser algo excepcional pero ya en ella se dejaban entrever algunos resquicios en su contra. Según estas impresiones iniciales tenemos tres compiladores que en principio de más completos a menos completos serían el de Metacomco, el de Digital y el peor el de GST. ¡QUE EQUIVOCADO ESTABA!. Todos tienen sus pros y sus contras . Desde aquí he de decir que el de Digital aún no le he catado, aunque Salvador Merino me ha hecho algunos comentarios bastante sugestivos de los problemas que con él aparecen).

Trabajando con el compilador de Metacomco, podemos suponer perfectamente que en vez de nuestro QDOS estamos trabajando en UNIX, de hecho las funciones y macros de su librería se definen en varios niveles de complicación y en alguno de ellos está un trabajo igualito al del UNIX, siendo el código "C" fuente de muchas de sus funciones de librería calcos auténticos del UNIX, con todas sus virtudes... y ¡sus defectos!. El compilador de hecho se monta un sistema de asignación de memoria y un sistema de manejo de canales independiente en parte del QDOS siguiendo las normas del UNIX, que de no limitarlo en el primer paso de compilación nos deja al QDOS prácticamente sin memoria para trabajar, ¿para que hacer un sistema de entrada-salida a ficheros con buffer de un bloque si el QDOS tiene un subsistema de bloques maravilloso?, ¿Para que crear un gestor nuevo de memoria estilo UNIX con su altísima tendencia a la fragmentación, si el gestor de memoria del QDOS es de lo mejorcito que uno puede echarse a la cara? (No se porqué me da la sensación de que éstos "defectos" son los mismos que tenían las primeras versiones del paquete de PSION que venía con el QL y que llevaban a un manejo infame de los microdrives al dejar casi sin memoria al QDOS ( con el agravante en éstos programas de funcionar a través de un emulador de MS-DOS (para mayor referencia ver el número de Noviembre del 87 de Sinclair QL World))). Menos mal que el compilador te deja siempre abierta la puerta a llamadas de bajo nivel sin buffer e incluso de llamadas directas al QDOS, pudiéndose obviar estos "defectos". Otro de los problemas que tiene el compilador de Metacomco es que trata los punteros a matrices como punteros a toda una matriz y no como puntero al primer elemento de una matriz, problema que en un momento determinado nos puede venir bien pero que nos complica un poquito al manejo de las matrices mediante punteros en vez de mediante índices (aunque con un poquito de habilidad esto se puede evitar). Otro problema está en la rigidez de la conversión de tipos de datos en los retornos de funciones, rigidez comprensible en las funciones que trabajan con datos de tipo float o double pero incomprensible en los datos char, short int y long, obligándote a hacer continuos "cast" y declaraciones de tipo de ciertas funciones (sobre todo en las funciones de asignación de memoria). Otro problema, deriva de que siga los estándar de formato en los números de coma flotante, con lo que no podemos utilizar de un modo directo las llamadas de TRAP del QDOS que requieran números de coma flotante en formato de 48 bits.

El de GST tiene las ausencias de matrices de más de 2 dimensiones, estructuras, uniones y números de coma flotante. De ellas la más aparatosa pudiera ser la aritmética de coma flotante pero ello los miembros del club lo tenéis un poco soslayado con la librería que escribí para éste compilador que incluye un manejo total de estos aunque en un formato intermedio entre float y double que corresponde a los números de coma flotante del SuperBASIC. Los tipos uniones y estructuras así como las matrices multidimensionales son simulables en cualquier momento y a cualquiera se le ocurrirían sencillas funciones que lo suplieran (más cuando las estructuras en C sólo suponen una distribución de datos que no es asignable en bloque, como en PASCAL por ejemplo). El problema de conversión de datos del compilador de Metacomco, no existe en el de GST dado que hay una universalidad de comunicación de parámetros y de resultados de funciones de tipo int. Otro problema, éste si que insoslayable es que el preprocesador de macros no soporta parámetros por lo que todo el trabajo con parámetros hay que realizarlo forzosamente a través de llamadas a funciones (aunque dado el peculiar mecanismo de trabajo del compilador de GST si cambiamos el ensamblador original por uno con macros con parámetros...). Una restricción adicional es que un módulo de programa puede tener como máximo 64k aunque con ayuda del linker se pueden construir programas de cualquier longitud

El compilador de DIGITAL, a priori parece indicado para aquellos que teniendo un buen dominio del SuperBASIC quieran adentrarse en el C. dado que parece construido con los elementos del SuperBASIC, a los que se han añadido elementos típicos del C como los macros y los punteros. De hecho pudiera decirse que es un compilador de SuperBASIC ampliado con sintaxis estilo C con eso sí un buen aprovechamiento del QDOS (no es de extrañar dado que es el SuperBASIC el lenguaje de alto nivel que mejor aprovechaba el QDOS) y según parece el compilador más rápido a la hora de efectuar su cometido. Como digo aún no he tenido ocasión de catarlo pero hay algo que me parece una seria restricción: los números enteros que maneja son como máximo de 16 bits, lo que lleva a su vez a que el máximo código de un programa sea de 64 Kbytes (lo cual en un lenguaje a base de librerías pueden llenarse con relativa facilidad). Otro problema que tiene respecto a los otros dos es que no es posible acceder de un modo más o menos directo a la inclusión de código en ensamblador, posibilidad bastante asequible en el de Metacomco y absolutamente fácil y natural en el de GST. Como bueno, parece que éste compilador está muy dirigido al QL y puede que en futuras versiones si se corrigen estos defectos pudiera ser el compilador de C ideal para el mismo.

En cuanto al modo de trabajo, el compilador de Metacomco genera en dos pasos código en formato relocalizable Sinclair que mediante un linker (en éste caso de GST) se monta con las librerías para crear un programa objeto.

El de GST genera en un sólo paso un listado de fuente en ensamblador listado en el que pueden ir como comentarios las líneas del programa fuente en C, después éste listado de ensamblador se ensambla con un ensamblador y se linka mediante un linker (el de GST como es obvio) para formar el código objeto. (Este sistema permite a los "ensambladoradictos" optimizar el código fuente en el listado de ensamblador e introducir a este nivel cualquier modificación que se nos ocurra).

El de DIGITAL genera en un paso un código interlinkable no estándar que luego se linka con un linker específico siendo el único que genera código objeto en dos únicos pasos.

Las ventajas que sacaría de cada uno de los compiladores son las siguientes:

El compilador de DIGITAL, es rápido, muy relacionado con el QDOS y fácil de usar partiendo de programas escritos en SuperBASIC (parece).

El compilador de Metacomco es el más sofisticado. Los ficheros fuente son transportables a cualquier ordenador con compilador Lattice y casi sin modificaciones a cualquier "C" basado en el UNIX V$7. El acceso desde ensamblador es bastante sencillo y genera un código en el que se realizan bastantes esfuerzos de optimización.

El compilador de GST proporciona una libertad casi absoluta en cuanto a tipos de parámetros, una integración total con el código en ensamblador, permite funciones con número variable de parámetros, y al igual que el de Metacomco permite detectar parámetros y canales de entrada y de salida estándar al arrancar la ejecución de un programa. (En el de Metacomco un poco más complicado lo de los canales). Permite asimismo optimizar el código en ensamblador generado por el compilador a gusto del programador.

Después de ver los dos compiladores en acción (el de Digital espero verle algún día), resulta un poco difícil decidirse por uno o por otro. No cabe duda que el de Metacomco es el más completo pero tiene algunas sutilezas que obligan a estar al programador muy alerta. El de GST es algo más flexible pero obliga al programador a realizar algunas funciones que el de Metacomco ya facilita (ahora estas funciones basta con escribirlas una sola vez). Respecto al aprovechamiento del QL, para mí creo que el de GST tiene una mayor integración que el de Metacomco; el de DIGITAL, sobre el papel parece que tiene una excepcional integración en este sentido aunque ya señalo las graves restricciones que tiene la primera versión

En cuanto al paquete en sí, el paquete de GST puede resultar atractivo en el sentido de que dispondríamos con el mismo paquete de un buen C un fenomenal macroensamblador un linker y un bastante buen editor, aparte de un programa de control escrito en C y un modificador de ventanas para mejorar el aspecto inicial de nuestros programas.

Siento si dejo indeciso a alguno, pero aunque estéis indecisos sobre cual creo que nadie debiera de perder la oportunidad de intentar comprender mejor éste lenguaje, dado que cada vez existen más y más librerías orientadas a casi cualquier aplicación, librerías que se pueden utilizar casi en cualquiera de los muchos ordenadores que hay en el mercado.


Sinclair QL Recursos en Castellano Alojado en / Hosted at:
Sinclair QL Recursos en Castellano
Sinclair QL Spanish Resources