Está en la página 1de 6

Ejercicio 2

Errores que se detectan en compilación


A continuación, se describen los mensajes más comunes que muestra el
compilador. Se ofrecen ejemplos de código para ilustrar las causas del error, pero
debe tenerse en cuenta que cada programa tiene una estructura diferente, y, por
tanto, el error puede aparecer por causas de alto nivel diferentes.

1. `variable' undeclared (first use in this function)

Este es uno de los más comunes y a la vez más fáciles de detectar. El


símbolo que se muestra al comienzo del mensaje se utiliza, pero no ha sido
declarado. Sólo se muestra la primera de las apariciones.

2. warning: implicit declaration of function `...'

Esta advertencia aparece cuando el compilador encuentra una función que


se utiliza en el código y de la que no tienen ningún tipo de información
hasta el momento. El compilador asume que la función devuelve un entero,
y continúa.

Estas advertencias son las que se recomienda eliminar antes de probar la


ejecución del programa. Dependiendo de la situación, hay varias formas de
eliminar este mensaje. El compilador necesita saber cómo se define la
función que ha encontrado. Para ello, en un lugar anterior en el fichero se
debe incluir, o la definición de la función o su prototipo (el tipo de dato que
devuelve, seguido de su nombre, los paréntesis con la definición de los
parámetros y un punto y coma).

Si esta información (la definición de la función) se necesita en múltiples


ficheros, entonces, en lugar de escribir la misma información en cada uno
de ellos se recomienda incluir el prototipo en un fichero que es luego
incluido en donde se necesite a través de la orden #include del pre-
procesador. Recuerda que el código de una función sólo puede estar
presente en un único fichero de código. Si el compilador se lo encuentra en
más de un fichero, entonces se producirá un error por haber definido una
función múltiples veces.
También puede darse el caso de que la información que se solicita esté
contenida en un fichero a incluir por tratarse de una función en una
biblioteca. Para consultar si la función está en una de las bibliotecas
estándar de C se recomienda utilizar el comando man seguido por el
nombre de la función. Si es parte de una biblioteca, en la misma página de
manual se muestra qué fichero hay que incluir en el código.

3. warning: initialization makes integer from pointer without a cast

Esta advertencia nos dice que hemos utilizado un puntero en un contexto


en el que se espera un entero. Esto está permitido en C y el compilador
sabe qué hacer para traducir el código, pero igualmente se notifica por si se
quiere “confirmar” esta operación mediante un cast. El siguiente código
muestra un ejemplo que produce esta advertencia.

int main (void)


{
char c = "\n”; /* ¿incorrecto? */
return 0;
}

En la primera línea se asigna un puntero a letra (pues una cadena entrecomillada


se almacena por debajo como una dirección de memoria, que es la que contiene
la primera letra) a una letra. A pesar de que c está definida como una letra, el
compilador la trata como un entero, lo cual es legal. La cadena de texto "\n" se
toma como un puntero, y de ahí se deriva el mensaje de advertencia. Se está
asignando un puntero a una variable que no lo es y que puede ser considerada
como un entero, y además, no se está utilizando un cast.

En la mayoría de los casos esta asignación es en realidad un error del


programador y por tanto necesita ser corregido. Pero es posible que se quiera
manipular un puntero como un número tal y como se muestra en el siguiente
programa:

int main (void)


{
int value = "\n"; /* Asignación correcta */
return 0;
}
4. dereferencing pointer to incomplete type

Este error aparece cuando se utiliza un puntero a una estructura de datos para
acceder a alguno de sus campos, pero el compilador no tiene información
suficiente sobre esa estructura de datos. El siguiente programa muestra esta
situación:

struct btree * data;


int main (void)
{
data->size = 0; /* Información incompleta */
return 0;
}

5. warning: control reaches end of non-void


function

Esta advertencia aparece cuando una función se ha declarado como que


devuelve un resultado y no se incluye ningún comando return para devolver
ese resultado. Por tanto, o se ha definido incorrectamente la función, o se
ha olvidado este comando. El compilador igualmente genera el ejecutable y
aunque la función no devuelva resultado, el compilador sí devuelve un
resultado a la función que ha hecho la invocación.

Bibliografía

[Gough05] Brian J. Gough. An Introduction to GCC. Network Theory


Ltd. Copyright © 1995 Network Theory Lt

http://www.it.uc3m.es/pbasanta/asng/course_notes/ch13s12.html
Jercisio 6
La Tabla de Símbolos
Un compilador utiliza una tabla de símbolos para llevar un registro de la información sobre el
ámbito y el enlace de los nombres. Se examina la tabla de símbolos cada vez que se encuentra un
nombre en el texto fuente. Si se descubre un nombre nuevo o nueva información sobre un
nombre ya existente, se producen cambios en la tabla.

Un mecanismo de tabla de símbolos debe permitir añadir entradas nuevas y encontrar las
entradas existentes eficientemente. Los dos mecanismos para tablas de símbolos presentadas en
esta sección son listas lioeal.es y tablas de dispersión. Cada esquema se evalúa basándose en el
tiempo necesario para añadir n entradas y realizar e consultas. Una lista lineal es lo más fácil de
implantar, pero su rendimiento es pobre cuando e y n sé vuelven más grandes. Los esquemas de
dispersión proporcionan un mayor rendimiento con un esfuerzo algo mayor de programación y
gasto de espacio. Ambos mecanismos pueden adaptarse rápidamente para funcionar con la regla
del anidamiento más cercano.

Es útil que un compilador pueda aumentar dinámicamente, la tabla de símbolos durante la


compilación. Si la tabla de símbolos tiene tamaño fijo al escribir el compilador, entonces el tamaño
debe ser lo suficientemente grande como para albergar cualquier programa fuente. Es muy
probable que dicho tamaño sea demasiado grande para la mayoría de los programas e inadecuado
para algunos.

Entradas de la tabla de símbolos


Cada entrada de la tabla de símbolos corresponde a la declaración de un nombre. El formato de
las entradas no tiene que ser uniforme porque la información de un nombre depende del uso de
dicho nombre. Cada entrada se puede implantar como un registro que conste de una secuencia de
palabras consecutivas de memoria. Para mantener uniformes los registros de la tabla de símbolos,
es conveniente guardar una parte de la información de un nombre fuera de la entrada de la tabla,
almacenando en el registro sólo un apuntador a esta información.

No toda la información se introduce en la tabla de símbolos a la vez. Las palabras clave se


introducen, si acaso, al inicio. El analizador léxico busca secuencias de letras y dígitos en la tabla de
símbolos para determinar si se ha encontrado una palabra clave reservada o un nombre. Con este
enfoque, las palabras clave deben estar en la tabla de símbolos antes de que comience el análisis
léxico. En ocasiones, si el analizador léxico reconoce las palabras clave reservadas, entonces no
necesitan aparecer en la tabla de símbolos. Si el lenguaje no convierte en reservadas las palabras
clave, entonces es indispensable que las palabras clave se introduzcan en la tabla de símbolos
advirtiendo su posible uso como palabras clave.

La entrada misma de la tabla de símbolos puede establecerse cuando se aclara el papel de un


nombre y se llenan los valores de los atributos cuando se dispone de la información. En algunos
casos, el analizador léxico puede iniciar la entrada en cuanto aparezca un nombre en los datos de
entrada. A menudo, un nombre puede indicar varios objetos distintos, quizás incluso en el mismo
bloque o procedimiento. Por ejemplo, las declaraciones en C.

Utilizan x como entero y como etiqueta de una estructura con dos campos. En dichos casos, el
analizador léxico sólo puede devolver al analizador sintáctico el nombre solo (o un apuntador al
lexema que forma dicho nombre), en lugar de un apuntador a la entrada en la tabla de símbolos.
Se crea el registro en la tabla de símbolos cuando se descubre el papel sintáctico que desempeña
este nombre. Para las declaraciones de (1), se crearían dos entradas en la tabla de símbolos para x;
una con x como entero y otra como estructura.

Los atributos de un nombre se introducen en respuesta a las declaraciones, que pueden ser
implícitas. Las etiquetas son a menudo identificadores seguidos de dos puntos, así que una acción
asociada con el reconocimiento de dicho identificador puede ser introducir este hecho en la tabla
de símbolos. Asimismo, la sintaxis de las declaraciones de procedimientos especifica que algunos
identificadores son parámetros formales.

Datos que se almacenan:


Para un array:
 Tipo de los elementos.
 Número de elementos.
 Limites inferior y superior.
Para una función:
 Número de parámetros.
 Tipo de los parámetros.
 Forma de paso de parámetros.
 Tipo de retorno.

Operaciones Principales.
 Insertar: introduce un símbolo tras una declaración.
 Buscar: recupera información asociada a un símbolo.
 Eliminar: borra la información.
Ejemplo de Uso I.

Declaración previa al uso de variables:


 En las declaraciones, inserción en la TS.
Aparición de una variable en una sentencia, búsqueda en la TS:
 Si se encuentra Fue declarada.
 Si no se encuentra Error de compilación.
Ejemplos de Uso II.

Acceso a una posición de un array:


 Declaración > Inserción en la TS.
1. Acceso a un array > Búsqueda en la TS.
2. Comprobación de tipo array.
3. Comprobación acceso a una posición válida.

http://cidecame.uaeh.edu.mx/lcc/mapa/PROYECTO/libro32/43__la_tabla_de_smbolos.html

http://compiinterprt2016ugbclass.blogspot.com/2016/05/tabla-de-simbolos.html

También podría gustarte