Download Ligadura de una Variable

Document related concepts

Clausura (informática) wikipedia , lookup

C Sharp wikipedia , lookup

Rust (lenguaje de programación) wikipedia , lookup

Common Lisp wikipedia , lookup

Polimorfismo (informática) wikipedia , lookup

Transcript
Lenguajes de Programación
E.S. Ingeniería Informática
Tema 2. Variables, ámbitos y comprobación de tipos
1. Variables
1.1. Nombre
1.2. Dirección
1.3. Tipo
1.4. Valor
2. Ligadura(binding)
2.1. Ligadura de tipos
• Ligadura estática de tipos
• Ligadura dinámica de tipos
2.2. Ligadura de espacio y tiempo de vida
• Variables estáticas
• Variables dinámicas de pila
• Variables dinámicas de montón (explícitas e implícitas)
3. Tipos
3.1. Comprobación de tipos
3.2. Disciplina de tipos
3.3. Compatibilidad de tipos
4. Ámbito
4.1. Ámbito estático
4.2. Ámbito dinámico
4.3. Entorno de referencia
5. Constantes
6. Inicialización de variables
6.1. Variables no inicializadas
Departamento de Informática
1
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
Bibliografía
Básica
Bal, H.E., Grune, D., Programming Languages Essentials, Addison-Wesley, 1994. Págs. 36-37.
Sebesta, R.W., Concepts of Programming Languages, 4 ed, Addison-Wesley, 1999. Págs. 155194.
Complementaria
Dershem, H.L., Jipping, M.J., Programming Languages: Structures and Models, 2 ed, PWS
Publishing Company, 1995. Págs. 52-63, 74-80.
Fischer, A.E., Grodzinsky, F.S., The Anatomy of Programming Languages, Prentice-Hall, 1993.
Págs. 163-196.
Ejercicios
1º Razona sobre la veracidad de las siguientes frases que hacen referencia a los lenguajes
imperativos.
a) “Todas las variables disponen de un nombre o identificador.”
b) “Cada identificador en un programa tiene siempre asociada una sola dirección de
memoria.”
c) “Es posible tener varios identificadores que hacen referencia a la misma dirección de
memoria.”
d) “La vinculación dinámica de tipos consiste en asociar tipos a variables a través de
convenciones sintácticas (por ejemplo, en algunos lenguajes estas convenciones hacen
referencia a la letra por la que comienza o el símbolo en el que acaba el nombre de la
variable)”.
e) “Las variables de tipo apuntador a otros objetos son siempre variables dinámicas de
montón”.
f) “En todos los lenguajes imperativos, todas las variables locales declaradas en
subprogramas son variables dinámicas de pila”.
g) “No hay ninguna diferencia entre subtipo y tipo derivado de un tipo existente”.
h) “Pascal es un lenguaje con disciplina de tipos”.
i) “En Pascal, las variables creadas mediante la utilización de new se caracterizan porque
el espacio que se les vincula se toma de la pila de ejecución”.
j) “Si un lenguaje de programación hace una evaluación dinámica del ámbito, entonces es
imposible realizar una comprobación de tipos estática de las referencias no locales”.
2º ¿Qué entendemos por ligadura estática de tipos? ¿Mediante qué distintas formas realizan los
lenguajes de programación la ligadura estática de tipos? (Menciona al menos un lenguaje
para cada una de las formas.) ¿Qué ventajas aporta la ligadura estática de tipos sobre la
dinámica?
3º La ligadura dinámica de tipos está muy relacionada con las variables dinámicas de montón
del tipo implícitas. Explica esta relación.
Departamento de Informática
2
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
4º Distingue entre:
a) Ligadura estática de tipos, disciplina de tipos y ligadura dinámica de tipos.
b) Coacción, error de tipos y comprobación de tipos.
c) Compatibilidad de tipos nominal y compatibilidad de tipos estructural.
5º En Haskell no es necesario declarar explícitamente el tipo de los objetos que se definen y, sin
embargo, es un lenguaje con disciplina de tipos. ¿Cómo explicas esto? Aunque, como
decimos, no es necesario, existen algunas razones por las que puede ser adecuado escribir las
declaraciones. ¿Cuáles son esas razones?
6º ¿En qué categorías se clasifican las variables atendiendo a la manera en que se produce la
ligadura de espacio? Explica brevemente cómo se realiza dicha ligadura en cada uno de los
tipos.
7º Cuando, en tiempo de ejecución, se entra en un bloque, las variables locales ya no contienen
los valores que almacenaban la última vez que fue ejecutado dicho bloque. ¿Por qué ocurre
esto?
8º Dado el siguiente esqueleto de programa escrito en C, dibuja un rectángulo alrededor de
cada uno de sus bloques, etiquétalos con las letras A, B, C, etc. y responde a las siguientes
preguntas.
int x, y, z;
fun1()
{
int j, k, l;
{
int m, n, x;
…
}
}
fun3()
{
int y, z, k;
…
}
main()
{ … }
a)
b)
c)
d)
e)
f)
Menciona un bloque que esté anidado dentro de otro bloque.
¿En qué ámbitos son accesibles a la vez las variables globales x, y, z?
¿Qué variables son accesibles desde la función main?
¿Son k de fun1 y k de fun3 la misma variable? Razona la respuesta.
¿Son las variables globales y y z accesibles desde fun3? Razona la respuesta.
¿En qué bloques j hace referencia a una variable local? ¿En qué bloques j es una
variable no local?
g) ¿En que bloque o bloques pueden usarse a la vez m y k?
Departamento de Informática
3
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
9º Indica qué valor de x se imprime en el procedimiento sub1 suponiendo tanto ámbito
estático como ámbito dinámico.
program pregunta_9;
var x: integer;
procedure sub1;
begin
writeln(‘x = ‘, x);
end;
procedure sub2;
var x: integer;
begin
x := 10;
sub1
end;
begin {de pregunta_9}
x := 5;
sub2;
end. {de pregunta_9}
10º ¿Qué es el ámbito de una variable de programa? Define el término bloque. En el siguiente
esqueleto de programa indica cuáles son los entornos de referencia en los puntos A y B, tanto
para el caso de ámbito estático como para el de ámbito dinámico.
program pregunta_10;
var a,b,c: integer;
begin
…
{B}
p3
end; {de p2}
procedure p1;
var b: integer;
begin
…
{A}
end; {de p1}
procedure p4;
var b: integer;
begin
…
p2
end; {de p4}
procedure p2;
var b,c: integer;
procedure p3;
var a: integer;
begin
…
p1
end; {de p3}
Departamento de Informática
begin
…
p4;
end. {de pregunta_10}
4
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
Tema 2. Variables, ámbito y comprobación de
tipos
1. Variables
♦ Variable: (nombre, dirección, valor, tipo, tiempo de vida, ámbito)
1.1. Nombre
♦ Nombre o identificador: cadena de caracteres empleada para
reconocer alguna entidad del programa
♦ Los nombres de variables son los identificadores más numerosos en los
programas, aunque no todas las variables tienen nombre
♦ Subprogramas, parámetros formales y otras entidades de programa
también poseen nombre o identificador
♦ Cuestiones relativas al diseño de nombres:
1. ¿Cuál es la longitud máxima de un identificador?
2. ¿Pueden emplearse caracteres conectores?
3. ¿Se distinguen mayúsculas de minúsculas?
4. ¿Las palabras especiales son palabras reservadas o palabras clave?
♦ ¿Cuál es la longitud máxima de un identificador?
•
Algunos lenguajes limitan el número de caracteres (31 en C),
mientras que otros, como Ada, no lo hacen
♦ ¿Pueden emplearse caracteres conectores?
•
El conector más empleado es _
Departamento de Informática
5
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ ¿Se distinguen mayúsculas de minúsculas?
•
•
•
Lenguajes como C, C++, Modula-2 o Java distinguen el uso de
mayúsculas y minúsculas en los identificadores
Ej. de tres nombres distintos en C: suma, Suma, SUMA ⇒ problemas
de legibilidad (nombres que parecen muy similares denotan
entidades distintas). Solución: utilizar solamente minúsculas
En Java (o Modula-2) muchos nombre predefinidos incluyen
mayúsculas y minúsculas. Ej.: nombre del método para convertir
una cadena de caracteres en un valor entero → parseInt
(ParseInt o parseint son incorrectos) ⇒ problema para escribir
los programas (hay que recordar la forma en que se escriben estos
nombre predefinidos)
♦ ¿Las palabras especiales son palabras reservadas o palabras clave?
•
•
Palabras especiales: indican acciones a realizar o se emplean
para separar entidades sintácticas de los programas. Pueden ser:
palabras clave o palabras reservadas
Palabras clave: sólo son palabras especiales en determinados
contextos
Ej: Fortran
REAL ALTURA
INTEGER REAL
REAL = 8.25
•
•
•
REAL INTEGER
Aunque tanto el compilador como los programadores distinguen un
identificador de una palabra especial por su contexto, el uso de
palabras clave puede conllevar problemas de legibilidad
Palabras reservadas: palabra especial de un LP que no puede
emplearse como identificador
Nombres predefinidos: nombres que tienen un significado
predefinido pero que puede ser cambiado (redefinido) por el usuario
Ej: Ada (integer, float), Pascal (readln, writeln, trunc,
round), C (printf, scanf)
Departamento de Informática
6
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
1.2. Dirección
♦ Direccion de una variable: dirección de memoria a la que está
asociada
♦ Un mismo nombre puede tener asociados diferentes direcciones en
lugares diferentes del programa (funciones f1 y f2 empleando la
variable i) o en momentos diferentes durante la ejecución del
programa (activaciones recursivas de un subprograma)
♦ La dirección de una variable se denomina l-valor → la aparición de una
variable en la parte izquierda de una asignación denota su dirección
Alias
♦ Alias: cuando se usa más de un nombre de variable para referenciar la
misma dirección
♦ Son un obstáculo a la legibilidad y verificación de programas. Ej: si A y
B son alias ⇒ cualquier cambio en A también cambia B y viceversa
♦ Formas de crear alias:
•
Registros variantes de Pascal y Ada o uniones de C y C++:
−
−
Medio de ahorrar espacio: la misma dirección se usa para
almacenar tipos diferentes en momentos diferentes
Medio de evitar las reglas de tipos del lenguaje: permite
manipular diferentes tipos de datos en la misma localización de
memoria
Departamento de Informática
7
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
En lenguajes con apuntadores, dos variables apuntador son alias
cuando apuntan a la misma localización de memoria. En C y C++, si
un apuntador hace referencia al espacio designado por un nombre
de variable, este nombre y el apuntador son alias
Ej: C
int a, *pa;
…
pa = &a;
/* pa y a son alias */
…
•
Empleando paso de parámetros por referencia a los subprogramas
1.3. Tipo
♦ Tipo de una variable: determina el rango de valores que puede tomar
la variable y el conjunto de operaciones definidas para los valores del
tipo
Ej. integer: [-32768..32767], {+, -, *, /}
1.4. Valor
♦ Valor de una variable: contenido de la celda o celdas de memoria
asociadas a las variables
♦ El valor de una variable se denomina r-valor → la aparición de una
variable en la parte derecha de una asignación denota su valor (Para
acceder a un r-valor primero debe determinarse su l-valor)
2. Ligadura (binding)
♦ Ligadura: asociación entre un atributo y una entidad
♦ El momento en el que se produce se denomina tiempo de ligadura.
Ejemplos:
•
Tiempo de compilación → la ligadura de una variable de un
programa en Pascal a su tipo de datos
Departamento de Informática
8
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
•
•
E.S. Ingeniería Informática
Tiempo de linkado → la ligadura de una llamada a un subprograma
de biblioteca al código del subprograma
Tiempo de carga → la ligadura de ciertas variables (ej: globales) a
sus celdas de memoria (su dirección)
Tiempo de ejecución → la ligadura de las variables locales (no
estáticas) a sus celdas de memoria
♦ Ligadura estática: si ocurre antes del tiempo de ejecución y
permanece inalterable durante la ejecución del programa
♦ Ligadura dinámica: si ocurre durante del tiempo de ejecución o
puede cambiar en el transcurso de la ejecución del programa
2.1. Ligadura de tipos
♦ Antes de que una variable pueda ser referenciada en un programa debe
haber sido ligada a un tipo de dato. Aspectos importantes: cuándo se
liga el tipo y cómo se especifica
A. Ligadura estática de tipos
♦ Puede hacerse mediante:
•
•
Declaración explícita: se utiliza una sentencia que declara una
lista de identificadores como de un tipo determinado
Declaración implícita: forma de asociar variables con tipos a
través de convenciones sintácticas. La primera aparición del
identificador constituye su declaración implícita
−
−
Ejemplos de LP: Fortran, Basic, Perl
Problema: variables no declaradas explícitamente de manera
accidental por el programador → toman un tipo por defecto
Departamento de Informática
9
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
Algoritmo de inferencia de tipos: determina los tipos de las
variables que intervienen en las expresiones sin que sean declaradas
de forma explícita por el programador o da un mensaje de error si
no puede inferirse
Ej: Haskell
f x y | x == True = y * y
| otherwise = y / 2
B. Ligadura dinámica de tipos
♦ El tipo no se especifica mediante una sentencia de declaración, sino
cuando se le asigna un valor mediante una sentencia de asignación ⇒
se liga al tipo del valor, variable o expresión de la parte derecha de la
asignación (APL, SNOBOL4)
♦ Ventaja: proporciona muchísima flexibilidad de programación
Ej: APL
lista ← 3.5 8.3 0.7 10.1
(tipo: lista de reales de long. 4)
lista ← 15
(tipo: variable entera)
♦ Desventajas:
•
No se detectan incorrecciones de tipo en las asignaciones. El tipo de
la parte izquierda simplemente se cambia al de la derecha
Ej:
i, x almacenan valores de tipo entero
y almacena un valor de tipo real
si por error escribimos
i ← y
en lugar de
i ← x
⇒ no se detecta el error, sino que el tipo de i se cambia a real.
En lenguajes con ligadura estática de tipos (Pascal, Ada) el
compilador detectaría el error. Aunque en otros (C), en muchas
ocasiones el tipo de la parte derecha se convierte
automáticamente al de la izquierda
Departamento de Informática
10
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
El coste de implementación de la ligadura dinámica de atributos es
mayor, sobre todo en tiempo de ejecución:
−
−
−
Comprobación de tipos
Mantenimiento del descriptor asociado a cada variable en el que
se almacena el tipo actual
Cambio en el tamaño de la memoria asociada a la variable
2.2. Ligadura de espacio y tiempo de vida
♦ Proceso de asignación: ligar celdas de memoria, tomadas de zonas
de memoria disponible, a variables
♦ Proceso de desasignación: desligar las celdas de memoria de la
variable y devolver las celdas a las zonas de memoria disponible
♦ Tiempo de vida de una variable de programa: tiempo durante el cual
la variable está ligada a una localización específica de memoria ⇒
tiempo entre asignación y desasignación de espacio
♦ Clasificación de las variables en cuatro categorías atendiendo a sus
tiempos de vida y a la zona de memoria desde donde se realiza la
asignación
A. Variables estáticas
♦ Se ligan a celdas de memoria antes de que comience la ejecución del
programa y permanece ligada a las mismas celdas hasta que acaba la
ejecución del programa
♦ Las variables globales son variables estáticas
♦ Puede ser conveniente declarar variables en subprogramas que
retengan el valor entre ejecuciones diferentes → variables estáticas
en subprogramas (ej. static en C)
Departamento de Informática
11
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ventaja principal: eficiencia
•
•
Todas pueden tener direccionamiento directo (otros tipos de
variable necesitan direccionamiento indirecto que es más lento)
No hay sobrecarga en tiempo de ejecución por asignación o
desasignación de espacio
♦ Desventaja: reducida flexibilidad
•
Si un LP no dispone de otro tipo de variables ⇒ no se soportan
programas recursivos
B. Variables dinámicas de pila
♦ La ligadura de espacio se produce cuando se elabora la sentencia de
declaración, exceptuando las que se ligan estáticamente
♦ Elaboración de una sentencia de declaración: proceso de asignación y
ligadura de espacio indicada por la declaración que tiene lugar cuando
la ejecución alcanza el código de dicha declaración ⇒ la elaboración se
produce en tiempo de ejecución
♦ Ej: los procedimientos en Pascal tienen:
•
•
Sección de declaración: se elabora justo antes de la ejecución del
código, cuando se llama al procedimiento
Sección de código
La asignación se produce en tiempo de elaboración y la
desasignación al devolver el control al procedimiento que realiza la
llamada
♦ El espacio se asigna en la pila de tiempo de ejecución
♦ Las variables locales (declaradas en subprogramas) son variables
dinámicas de pila (a excepción de las declaradas como estáticas)
Departamento de Informática
12
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ventajas:
•
•
Todas las variables comparten el mismo espacio de memoria (la
pila)
Permiten recursión → permite almacenar una copia diferente de las
variables locales para cada una de las llamadas recursivas
♦ Desventaja:
•
Sobrecarga en tiempo de ejecución debido a la asignación y
desasignación de espacio en la pila
C. Variables dinámicas de montón (heap)
♦ Montón (heap): colección de celdas de almacenamiento cuya
estructura está muy desorganizada debido a la naturaleza imprevisible
de su uso
♦ Dos clases: explícitas e implícitas
C.1. Explícitas
♦ Variables sin nombre cuyo almacenamiento se asigna y desasigna en
tiempo de ejecución mediante la utilización por el programador de
instrucciones específicas
♦ Sólo pueden ser referenciadas mediante apuntadores
♦ La creación/destrucción de variables puede hacerse mediante un
operador (C++, Ada) o una función de biblioteca (C, Pascal)
Departamento de Informática
13
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ejemplo: Pascal
type
pnodo = ^nodo;
nodo
= record … end;
var
nuevo_nodo: pnodo;
…
begin
…
{ La ligadura del tipo es estática y
la de espacio dinámica}
new(nuevo_nodo);
…
dispose(nuevo_nodo);
…
end;
♦ Uso: estructuras dinámicas (listas, árboles, grafos, …)
♦ Desventajas:
•
•
Dificultad para usarlas correctamente
Coste en tiempo de ejecución en las operaciones de referencia,
asignación y desasignación
C.2. Implícitas
♦ Se les liga espacio del montón sólo cuando se le asignan valores (de
hecho, todos sus atributos se ligan cada vez que se produce una
asignación)
♦ Ejemplo: variables de APL
♦ Ventaja: flexibilidad en la programación → permite escribir código muy
genérico
Departamento de Informática
14
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Desventajas:
•
•
Dejan de detectarse algunos errores de tipo
Sobrecarga en tiempo de ejecución (asignación/desasignación de
espacio y resto de atributos)
3. Tipos
3.1. Comprobación de tipos
♦ Generalización de los conceptos de operandos y operadores para incluir
a subprogramas y sentencia de asignación:
•
•
Subprogramas → operadores cuyos operandos son sus parámetros
Asignación → operador binario cuyos operandos son la variable a la
que se asigna el valor y la expresión a evaluar
♦ Comprobación de tipos: actividad que nos asegura que los
operandos de un operador son de tipos compatibles
♦ Tipos compatibles: un tipo legal para el operador o un tipo que
atendiendo a determinadas reglas del lenguaje puede ser convertido
implícitamente mediante código generado por el compilador en un tipo
legal. Esta conversión automática se denomina coacción (coercion)
♦ Error de tipos: aplicación de un operador a un operando de tipo
inapropiado
♦ Si todas las ligaduras de tipos a variables son estáticas ⇒ las
comprobaciones de tipo pueden realizarse de forma estática
♦ Si hay ligadura dinámica de tipos a variables ⇒ debe realizarse una
comprobación dinámica de tipos (más costosa que en tiempo de
compilación)
Departamento de Informática
15
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ LP (Pascal, Ada, C) que permiten el almacenamiento en la misma celda
de memoria de valores de tipos diferentes en momentos distintos de la
ejecución (registros variantes y uniones) ⇒ la comprobación de tipos
para estas clases de datos debe ser dinámica ⇒ requiere mantener
durante la ejecución el tipo actual asociado a la celda de memoria ⇒ no
todos los errores pueden detectarse con una comprobación estática de
tipos
3.2. Disciplina de tipos (strong typing)
♦ Un lenguaje tiene disciplina de tipos si los errores de tipos se
detectan siempre ⇒ es necesario determinar los tipos de todos los
operandos, ya sea en tiempo de compilación o de ejecución
♦ Pascal
•
Cercano a tener disciplina de tipos pero no realiza comprobación de
tipos en los registros variantes (incluso puede omitirse la etiqueta
discriminatoria en dichos registros)
♦ Ada
•
•
Resuelve el problema de los registros variantes realizando
comprobación dinámica de tipos (sólo en este caso)
Tiene una función de biblioteca que permite extraer un valor de una
variable de cualquier tipo (como una cadena de bits) y usarlo como
un tipo diferente (no es una conversión de tipos) ⇒ se trata de una
suspensión temporal de la comprobación de tipos
♦ C
•
No tiene disciplina de tipos por:
−
−
No se realiza comprobación de tipos sobre las uniones
Permite funciones con parámetros sobre los que no se realiza
comprobación de tipos
Departamento de Informática
16
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Java
•
Tiene disciplina de tipos (no hay uniones)
♦ ML y Haskell
•
•
Poseen disciplina de tipos
Los tipos de los parámetros de las funciones (y de estas mismas) se
conocen en tiempo de compilación (ya sea por declaración del
usuario o por inferencia de tipos)
3.3. Compatibilidad de tipos
♦ Métodos:
•
Compatibilidad de tipos nominal: dos variables tienen tipos
compatibles si están ligadas al mismo nombre de tipo
Ej:
type
T = array [1..10] of integer;
var
a, b: T;
begin
a := b;
•
Compatibilidad de tipos estructural: dos variables tienen tipos
compatibles si sus tipos tienen la misma estructura
Ej:
type
T = array [1..10] of integer;
S = array [1..10] of integer;
var
a: S;
b: T;
begin
a := b;
Departamento de Informática
17
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
Equivalencia de declaración: dos variables tienen tipos
compatibles si uno de los tipos está definido con el nombre del otro
Ej:
type
T = array [1..10] of integer;
S = T;
var
a: S;
b: T;
begin
a := b;
♦ La mayoría de LP utilizan combinaciones de estos tres métodos de
compatibilidad
♦ Tipo anónimo: tipo asociado directamente con una variable mediante
una declaración sin proporcionarle un nombre
Ej. en Ada:
a, b: array (1..10) of INTEGER;
c: array (1..10) of INTEGER;
→ La interpretación es obvia usando compatibilidad de tipos
estructural
→ ¿Compatibilidad nominal? Ej. Ada a, b y c son incompatibles
♦ Compatibilidad de tipos nominal:
•
•
Fácil de implementar pero muy restrictiva
Ej. usando un lenguaje con interpretación estricta de la
compatibilidad de tipos nominal:
Departamento de Informática
18
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
type
tipo_indice = 1..100;
var
contador: integer;
indice: tipo_indice;
begin
contador := indice;
indice := contador;
♦ Compatibilidad de tipos estructural:
•
Debe compararse la estructura de ambos tipos, pero:
−
−
−
•
¿Son compatibles dos registros con la misma estructura pero
con nombres de campos diferentes?
¿Son compatibles arrays del mismo tipo y con el mismo número
de elementos pero con rangos de índices diferentes (0..9 /
1..10)?
¿Son compatibles tipos enumerados con el mismo número de
componentes pero literales diferentes?
No acepta diferencias entre tipos con la misma estructura
Ej:
type
longitud = real;
tiempo = real;
var
l: longitud;
t: tiempo;
→ l y t son compatibles (tienen la misma estructura), aunque
quizás no deberían considerarse equivalentes: son
abstracciones de diferentes categorías de valores del problema
Departamento de Informática
19
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
Subtipos y tipos derivados
♦ Subtipo: versión (posiblemente restringida en el rango) de un tipo
existente con el que es compatible. Evita uno de los problemas de la
compatibilidad de tipos nominal
•
Ej. Ada:
subtype Natural is Integer range 0..
Integer’Last;
subtype Temperatura is Integer range -20..45;
n: Natural;
i: Integer;
t: Temperatura;
→ Las siguientes asignaciones son posibles:
n := i;
i := n;
t := i;
→ Se necesita una comprobación en tiempo de ejecución que
asegure que el valor que se asigna está en el rango adecuado
→ Para la función:
function "**" (i: Integer; n: Natural)
return Integer;
y la llamada
j ** k;
el compilador comprueba que j y k sean del tipo Integer (o
de uno de sus subtipos). Durante la ejecución se asegura que
el valor actual de k esté en el rango de Natural. Un lenguaje
con compatibilidad de tipos nominal sólo aceptaría que j fuese
del tipo Integer y n del tipo Natural.
♦ Tipo derivado: nuevo tipo basado en algún otro previamente definido
con el que es incompatible, aunque sean estructuralmente idénticos.
Heredan todas las propiedades de su tipo padre. (También pueden
incluir restricciones sobre el rango)
Departamento de Informática
20
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
Ej. Ada:
type Longitud is new Float;
type Tiempo is new Float;
→ Las variables de estos tipos son incompatibles entre ellas y con
otras de tipo float (esta regla no se aplica a los literales como
12.5)
4. Ámbito
♦ Ámbito de una variable de programa: rango de sentencias en las que
es visible la variable
♦ Una variable es visible en una sentencia si puede referenciarse en
dicha sentencia
♦ Las reglas de ámbito de un lenguaje determinan cómo se asocian las
referencias a variables declaradas fuera del subprograma o bloque que
se está ejecutando con sus declaraciones ⇒ con sus atributos
♦ Una variable es local en una unidad de programa o bloque si está
declarada en él. Las variables no locales de una unidad de programa o
bloque son aquellas visibles en dicha unidad o bloque pero no
declaradas en él
4.1. Ámbito estático
♦ Ámbito estático (introducido por ALGOL 60): método de ligadura de
nombres a variables no locales que ocurre en tiempo de compilación
♦ En la mayoría de lenguajes con ámbito estático (C es una de las
excepciones) pueden anidarse los subprogramas → cada subprograma
crea su propio ámbito ⇒ el resultado es una jerarquía de ámbitos
Departamento de Informática
21
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ ¿Cómo se determinan los atributos de una variable en un lenguaje con
ámbito estático?
1º. Se busca su declaración local, y si no se encuentra
2º. Se continúa la búsqueda en el bloque que lo declara, su padre
estático. Si no se encuentra,
3º. Se continúa la búsqueda en la unidad que declara a esta última. Así
hasta que se encuentra la declaración de la variable o se alcance la
unidad de declaración mayor ⇒ error: utilización de una variable no
declarada
♦ El padre estático de un subprograma y los padres estáticos de éste
hasta el programa principal se denominan antepasados estáticos
♦ Ejemplo:
procedure mayor;
var x: integer;
procedure sub1;
begin
… x …
end; {de sub1}
procedure sub2;
var x: real;
begin
…
end; {de sub2}
begin
…
end. {de mayor}
•
La referencia a la variable x en sub1 se corresponde con la
declaración de x en mayor
♦ En lenguajes con ámbito estático, una declaración de una variable
oculta cualquier declaración de otra variable con el mismo nombre en
un ámbito que englobe al que incluye dicha declaración
•
La referencia a la variable x en sub2 se corresponde con la
declaración en sub2 ⇒ se oculta la declaración de x en mayor
Departamento de Informática
22
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
E.S. Ingeniería Informática
Hay lenguajes que permiten hacer referencia a variables ocultas
declaradas en antepasados estáticos
Ej: Ada. Sintaxis: nombre_unidad_de_programa.nombre_variable
mayor.x
♦ Algunos lenguajes (herederos de ALGOL 60) permiten definir nuevos
ámbitos estáticos en mitad de código ejecutable ⇒ son variables locales
a esa sección de código. Son variables dinámicas de pila ⇒ se les
asigna espacio al comenzar la sección y se desasigna cuando se sale de
ella
♦ Las secciones de código en la que pueden definirse variables locales se
denominan bloques
•
•
•
•
Ej. de bloque en Ada:
…
declare temp: Integer;
begin
temp := x;
x := y;
y := temp;
end;
…
Los bloques son el origen de la expresión lenguajes
estructurados en bloques
Aunque a Pascal se le considera un lenguaje estructurado en
bloques no dispone de bloques no procedurales
En C, cualquier grupo de sentencia compuesta (secuencia de
sentencias englobadas entre llaves) puede definir un nuevo ámbito.
Ejemplo:
if (lista[i] < lista[j])
{
int temp;
}
temp := lista[i];
lista[i] := lista[j];
lista[j] := temp;
Departamento de Informática
23
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
•
•
E.S. Ingeniería Informática
Java permite que la definición de una variable aparezca en cualquier
lugar de una función → el ámbito de la variable comienza en la
sentencia de definición y acaba en el final del bloque que la incluye
Los ámbitos definidos por bloques se tratan igual que los creados
por subprogramas
Evaluación del ámbito estático
♦ Proporciona un método de acceso a variables no locales adecuado en la
mayoría de los casos
♦ Problemas:
•
•
Acceso a demasiados datos. Por ejemplo, todas las variables
declaradas en el programa principal son visibles en todos los
procedimientos, se desee o no
Los cambios pueden ser complicados:
principal
A
C
D
B
E
1. Es necesario acceder a variables de D desde E. Soluciones:
−
−
Mover E dentro de D ⇒ E deja de tener acceso al ámbito de
B
Mover las variables de D que necesita E a principal ⇒
puede accederse a ellas desde otros procedimientos.
Además, supongamos que D y E necesitan la variable x. Si
en A hay una variable con nombre x ⇒ oculta la variable x
que necesita D y hemos movido a principal
Departamento de Informática
24
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
2. E necesita llamar al procedimiento D. Soluciones:
−
•
Mover D dentro de principal ⇒ deja de tener acceso a las
variables de A
Esta falta de flexibilidad provoca una tendencia en los
programadores a usar más variables globales de las que necesitan
4.2. Ámbito dinámico
♦ Ámbito dinámico (APL, SNOBOL4): basado en la secuencia de
llamadas a subprogramas y no en la relación sintáctica entre ellos ⇒ el
ámbito sólo puede determinarse en tiempo de ejecución
♦ ¿Cómo se determinan los atributos de una variable en un lenguaje con
ámbito dinámico? En tiempo de ejecución:
1º. Se busca su declaración local, y si no se encuentra
2º. Se continúa la búsqueda en su padre dinámico, el subprograma
que realizó la llamada. Si no se encuentra,
3º. Se continúa la búsqueda en los antepasados dinámicos. Así
hasta que se encuentra la declaración de la variable. Si no se
encuentra la declaración en ningún antecesor dinámico ⇒ error en
tiempo de ejecución
Departamento de Informática
25
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ejemplo:
procedure mayor;
var x: integer;
procedure sub1;
begin
… x …
end; {de sub1}
procedure sub2;
var x: real;
begin
…
end; {de sub2}
begin
…
end. {de mayor}
•
•
Secuencia de llamadas: mayor → sub2 → sub1 ⇒ la referencia a
x en sub1 corresponde con la declaración de x en sub2
Secuencia de llamadas: mayor → sub1 ⇒ la referencia a x en
sub1 corresponde con la declaración de x en mayor
Evaluación del ámbito dinámico
♦ Una sentencia en un subprograma que contiene una referencia a una
variable no local puede relacionarse con una variable diferente cada vez
que se ejecuta ⇒ muchos tipos de problemas:
•
•
•
Durante el tiempo que transcurre entre el comienzo y la finalización
de la ejecución de un subprograma todas las variables locales del
subprograma son visibles en los subprogramas a los que se llame.
No hay forma de protegerlas de esta accesibilidad ⇒ programas
menos fiables que con ámbito estático
Imposibilidad de realizar una comprobación de tipos estática de las
referencias no locales (es imposible determinar estáticamente su
declaración)
Los programas son más difíciles de leer y seguir por un lector
humano
Departamento de Informática
26
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ventaja: el subprograma hereda el contexto de sus llamadores →
método de comunicación entre unidades de programa (menos seguro
que otros métodos, como el paso de parámetros)
4.3. Entorno de referencia
♦ Entorno de referencia de una sentencia: colección de todos los
identificadores visibles en dicha sentencia
•
•
Lenguajes con ámbito estático: el entorno de referencia de una
sentencia está compuesto por las variables declaradas en su ámbito
local más todas las variables visibles de sus antepasados estáticos
Lenguajes con ámbito dinámico: el entorno de referencia de una
sentencia está compuesto por las variables declaradas localmente
más todas las variables visibles del resto de subprogramas activos
Ej.: principal → sub2 → sub1
procedure sub1;
var a,b: integer;
begin
… {A}
end; {de sub1}
procedure sub2;
var b,c: integer;
begin
… {B}
sub1;
end; {de sub2}
procedure principal;
var c,d: integer;
begin
… {C}
sub2;
end. {de principal}
Punto
Entorno de referencia
A
a y b de sub1, c de sub2, d de
principal
B
b y c de sub2, d de principal
C
c y d de principal
Departamento de Informática
27
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
5. Constantes
♦ Constante: objeto al que se le liga un valor sólo en el momento en el
que se le liga el espacio ⇒ su valor no puede cambiarse por asignación
o por sentencia de entrada
♦ Ventajas:
•
•
Aumenta la fiabilidad y legibilidad de los programas
El valor aparece en una sola línea de programa ⇒ más fácil su
modificación
♦ Constantes manifiestas: constantes con ligadura estática de valores
•
•
Pascal: la declaración de una constante requiere un valor simple
Modula-2: permite expresiones constantes (constantes ya
declaradas, literales y operadores)
♦ Otros lenguajes (Ada, Java) permiten ligadura dinámica de valores a
constantes ⇒ pueden aparecer variables
•
Ada:
num_elementos: constant Integer := 2 * i + j;
6. Inicialización de variables
♦ Inicialización: ligadura de un valor a una variable en el momento en
el que también se le liga el almacenamiento
♦ Variables estáticas: inicialización sucede una sola vez antes del
momento de la ejecución
♦ Variables con ligadura dinámica de espacio: la inicialización también es
dinámica
Departamento de Informática
28
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Inicialización en algunos lenguajes:
•
Pascal: No tiene sentencias de inicialización
•
C: en la sentencia de declaración puede indicarse un valor inicial
Ej.: int i = 10;
•
Ada: la inicialización puede incluir nombres de otras constantes o
variables visibles en el momento de la elaboración de la inicialización
Ej.: contador: integer := num_elem + 1;
num_elem puede ser el nombre de una variable o constante
Variables no inicializadas
♦ Las declaraciones sin inicialización crean variables no inicializadas: se les
liga memoria pero su contenido es arbitrario y no puede ser
interpretado como un valor del tipo del objeto declarado. El uso de un
valor no incializado produce resultados impredecibles y debe evitarse
♦ Posibles aproximaciones que pueden utilizar los LP:
•
•
•
•
Se ignora el problema y se considera responsabilidad del
programador no emplear valores no inicializados. Poco elegante
Todas las declaraciones inicializan el espacio asignado a un valor
apropiado, definido para cada tipo básico. Por ej., punteros a null
y valores numéricos a cero. Puede llevar a errores
No existen declaraciones sin inicialización ⇒ el programador debe
proporcionar un valor de inicialización adecuado para cada elemento
declarado
Existe un valor especial para cada tipo denominado omega, que
representa la propiedad de ausencia de inicialización. Este valor se
propaga en las expresiones (omega + 3 → omega). Permite al
programador comprobar dinámicamente si una variable está o no
inicializada
Departamento de Informática
29
Área de Lenguajes y Sistemas Informáticos
Lenguajes de Programación
E.S. Ingeniería Informática
♦ Ejemplos de algunos LP:
•
•
•
Pascal: ignora el problema
Ada: inicializa apuntadores a null e ignora el problema para el
resto de tipos
C: inicializa las variables estáticas a una forma apropiada de cero.
Ignora el problema para el resto de las variables
Departamento de Informática
30
Área de Lenguajes y Sistemas Informáticos