Lenguaje de programación. Datos

Anuncio
TEMA 3: Datos
3.1
Variables
• Una variable es una séxtupla de atributos
• Nombre o identificador.
• Dirección.
• Valor.
• Tipo.
• Tiempo de vida.
• Ômbito.
3.1.1 Nombre o Identificador.
• Los identificadores más abundante son los que se refieren a nombres de variables. Pero también
hay variables sin nombre.
• Reglas que rigen el diseño de los (nombres) indentificadores ( en general).
• ¿Cúal es la longitud máxima del identificador ?.
• ¿Pueden emplearse caracteres conectores?.
• ¿Se distiguen mayúsculas de minúsculas?.
• ¿Las palabras especiales son palabras claves o reservadas?.
• Id o nombre: cadena de caracteres de longitud variable.
Ej:
C -> limita la longitud a 31 caracteres.
Ada -> no limitan la longitud.
C++-> No dice nada en la especificación.
• Caracteres conectores: La mayorÃ−a de los lenguajes permiten que se utilice el caracter...
• Distinción Mayusculas de Minusculas: C,C++,Modula-2 distinguen el uso de las mayúsculas de
las minúsculas ( son case-sensitive).
Ej:
Suma, suma, SUMA -> 3 identificadores diferentes.Violan el principio de legibilidad.
En Modula-2: WriteInt ( nombre de módulo predefinido). Hay que escribirlo asÃ− siempre.
• Palabras Clave o reservadas: if, while son palabras especilaes.
• Si las palabras son claves; se trata de palabras que sólo son especiales en ciertos contextos. Ej:
Fortran : REAL ALTURA ( ALTURA es del tipo REAL)
1
REAL = 8.5 ( aquÃ− REAL es un identificador )
REAL INTEGER
INTEGER REAL
• Se habla de palabras reservadas cuando son palabras especiales que no pueden emplearse por el
usuario como identificadores. En estos lenguajes que usan palabras reservadas hay:
• Identificadores predefinidos.Tienen un significado predefinido pero pueden cambiar de usuario.
• Ej: llamadas afunciones de librerÃ−a.
C-> printf, scanf
Pascal-> write, read
Ada-> get, put ( aquÃ− en Ada el usuario puede redefinir el sentido de estos identificadores).
3.1.2 Dirección:
• Es la dirección de memoria a la que está asociada la variable. Yo puedo tener un identificador “i”
en las funciones f1 y f2 y en cada una “i” tiene direcciones de memoria diferentes.
• Si f es una función recursiva: En cada activación del procedimiento i tiene una dirección de
memoria diferente en la pila A la dirección de memoria también se le conoce como L-valor:
v:= E ( para realizar la asignación necesito conocer la dirección de r ).
L - valor -> ( el valor de la parte izquierda de una operación de asignación ).
• Alias: Tendremos un alias cuando hay más de un nombre de variable para acceder a una misma
localización de memoria.
• Creación:
• Hay lenguajes donde se crean de forma explÃ−cita. Ej:
FORTRAN -> EQUIVALENZE
COBOL -> REDEFINES
• En Pascal y en Ada mediante registros variantes. En C y C++ mediante unions.
• Se puede acceder en momentos diferentes a nombres de variables diferentes.
Ej: Pascal;
Type coordenadas = record case clase:(cartesiana, polar) of
cartesiana: (x,y: real);
polar:(r,fi: real);
2
end;
• Otra forma de crear alias es empleando paso de parámteros por referencia en los subprogramas. ( si
pasas un parámetro por referencia ya tienes 2 referencias a esa variable ).
• En lenguajes con apuntadores cuando 2 o más apuntadores referencian la misma zona de memoria
tambien se están creando alias.
NOTA: Para nosotros todos los tipos no estructurados ocupan una celda .
3.1.3 Tipo
• El tipo de dato de una variable va a determinar:
• El rango de valores.
• El conjunto de operaciones definido para ese tipo de dato.
Ej:
rango de valores: -32768..32767.
Integer
operaciones : +, -, *, /.
3.1.4 Valor
• El valor de una variable es el contenido de la celda de memoria asociada a esa variable. Al contenido
de una celda de memoria se le denomina R-valor: v:= i + 1;
Para obtener el r-valor de una variable necesito saber primero el L-valor de esa variable.
3.1
Vinculación (Binding)
• Cuando se produce una asociación entre una atributo o entre una operación y un sÃ−mbolo. Al
momento e n el que se produce esa vionculación es a lo que se denomina tiempo de vinculación. En
general vamos a hablar siempre de:
• vinculación estática si ésta se produce antes del tiempo de ejecución y permanece inalterable
durante toda la ejeccución del programa.
• Vinculación dinámica: durante el tiempo de ejecuciòn o cambia en el transcurso del programa.
3.2.1 Vinculación de Tipos.
• En cualquier lenguaje de programación antes de la ejecución de una variable hay que saber la
vinculación de tipos.
• VINCULACIà N ESTÔTICA DE TIPOS.
Puede realizarse de manera explÃ−ctita o de una manera implÃ−ctita.
• De forma explÃ−cita: El lenguaje tiene una lista de variables a las que se asigna un tipo: int i,j;
3
• De forma implÃ−cita.- No se utilizan estas sentencias, sino que el tipo se asocia a través de
determinadas convenciones. La asociación de tipos se produce la 1º vez que aparece la variable. El
compilador ya entiende el tipo a través de las convenciones.
Ej:
BASIC, FORTRAN -> I,...,N
I = H * L ( el compilador deduce el tipo de las variables H y L.
• Hay otra forma del tipo de declaración implÃ−cita ( ML, HASKELL) donde se emplea el algoritmo
de inferencia de tipos. Si no se indica el tipo de las variables, entonces los lenguajes o infieren un tipo,
o presentan un mensaje de error .
• VINCULACIà N DINÔMICA DE TIPOS
• Hay que tener en antes de empezar este punto que las vinculaciones estática e implicita es total
• En este caso el tipo no se especifica mediante ningún tipo de declaración, sino cuando se le asigna
por primera vez mediante una sentencia de asignación.
Ej:
APL
LISTA <- 8.1, 3.0, 0.5, 6.25. ( lista de cuatro elementos de números reales ).
LISTA <- 3. ( un número entero ).
• Ventaja: Este tipo de programación da gran flexibilidad al programador.
• Desventajas:
• No se detectan muchos errores de tipos.
Ej:
i, x -> enteros.
y -> real.
I:= y / i:= x No da error en vinculación dinámica de tipos , convierte a i en real.
Existen también coacciones de tipo:
i:= y.
• El coste de implementación en tiempo de ejecución (elevado coste de asignación y desasignación
de espacio).
3.2.2 Vinculación de espacio y tiempo de vida.
4
• La vinculación de espacio significa que desde algunas zonas de memoria disponibles se vinculan
celdas de memoria a un a variable: asignación. El proceso de desasginación: se devuelve a una
zona de memoria libre el espacio que hasta entonces estaba asignado a una variable.
• Tiempo de vida de una variable: Es el tiempo durente el cual la variable está vinculada a un lugar
especÃ−fico de la memoria ( tiempo que transcurre entre la asignación y la desasignación).
• Vamos a clasificar la vinculación de espacio atendiendo al tiempo de vida de la variable.
• Variables estáticas. La vinculación de espacio se produce antes de que se comience a ejecutar el
programa. Permanecen vinculadas a las mismas celdas hasta que acaba la ejecución del programa.
Las variables globales son variables estáticas. Muchas veces en los subprogramas nos interesa que la
variable recuerde el valor entre llamadas diferentes: "sensibles a la historia". En C las variables
locales se puenden transformar en esáticas a través de static.
Sus ventajas son:
• La eficiencia
• Todas estas variables pueden tener un direcciónamiento directo.
• No hay sobrecarga de asignación o desasignación en tiempo de ejecución.
Su desventaja:
• Falta de flexibilidad, por ejemplo no se permite la recursividad.
• Variables dinámicas en pila. En este tipo de veriables la vinculación se produce en el momento de
la elaboración de la sentencia de declaración. Entendemos elaboración de la sentencia de
declaración cuando en el momento de la ejecucuión de sentencia se vincula espacio a las variables
que se indican. Esta elaboración está sucediendo en tiempo de ejecuacuón.
Ej: Pascal
VAR: sección de declaración -> se elabora antes de la ejecución del código.
BEGIN
sección del código -> variables locales.
END
Por tanto la asignación de espacio ocurre en tienpo de elaboración y la desasignación ocurre al finalizar el
subprograma (procedimiento o función).
• Se denominan de pila porque el espacio se asigna en la pila de ejecución. Cada vez que se ejecuta un
procedimiento aparece en la pila un bloque de asignación. Variables locales- > Se declaran en los
subprogramas.
Ventajas:
• Si todas la s variables son estáticas, debemos guartadar en la zona de memoria espacio para todas
ellas.
• Si el lenguaje proporciona variables dinámicas de pila, estoy utilizando el mÃ−nimo espacio para
todas las variables, a medida que voy utilizando procediminentos voy haciendo reserva de pila ( zona
5
común para todas las variables de pila).
• Permiten recursión.
Desventajas:
• Sobrecarga relativa en tinepo de ejecucuón.
• No son sensibles a la historia, no conocemos el valor que tenÃ−an al hacer una siguiente llamada.
• Variables dinámicas de Heap.
• Heap: colección de celdas de memoria que se caracteria por tener una estrucutura muy
desorganizada debido a que tiene un uso de sus celdas de manera impredecible.
• Variables dinámicas del Heap:
• ExplÃ−citas: Son variable sin nombre. Su asignación o desasiganción se realiza en tiempo de
ejecución, decidiendolo el programador ( coloca una instrucción allÃ−; al efecto ).Se referencian
mediante apuntadores
Ej:
Creacción / destrucción mediante operador:
C ++, new / delete.
Creacción / destrucción mediante función de librerÃ−a:
C; Pascal: malloc() / free(); new() / dispose ()
Ej:
C++
cnt *apentero;
.........................
apentero = new int; // Reservamos una celda del Heap
..........................
delete apentero; // Se desvincula ( la celda pasa a estar libre ).
• Se usan para crear estructuras del tipo lista, árboles...
Desvetajas: Sobrecarga en tienpo de ejcución (El coste en tiempo de ejecución son la asigneción + la
desasigneción + la referencia) y la dificultad de uso.
• Implicitas:
• La vinculación del espacio se produce casa vez que se le asignan valores a las variables ( no se
produce por la instrucción que coloca el programador ).
6
Ej:
APL
Lista <- 4.0, 3.5, 7.12
Lista <- 8.
Ventaja: Flexibilidad en la programación.
Desventajas:
- Sobrecarga que se produce en tiempo de ejecución.
- Se dejan de detectar algunos errores de tipo.
3.3
Tipos
3.3.1 Comprobación de Tipos.
• Los subprogramas son operadores; por tanto los parámetros de los subprogramas son los operandos
• Asignación -> operador binario.
Bajo estas suposiciones definimos:
• Comprobación de tipos: es la actividad que nos asegura que los operandos de un operador son de
tipos compatibles.
• Tipos compatibles: si se trata de un tipo legal paraa ese operador o bien atendiendo a algunas reglas
del lenguaje puede ser convertido (de manera Ã−mplicita atendiendo siempre a reglas del lenguaje y
empleando un código que genera el compilador a tal efecto ), en un tipo legal. Esta conversión se
llama coacción. ( coerción).
• ¿ Cuándo se produce un error de tipos ?. Cuando se emplea un tipo inadecuado del operador que se
está utilizando.
• Vinculación estática de tipos a variables .- comprobación de tipos puede ser estática. ( podemos
comprobarlo también en tiempo de compilacción ).
• Vinculación dinámica .- La comprobación debe ser dinámica.
• Pascal , Ada, C permiten estructuras de tipo registros variantes o uniones-> la comprobación
dinámica de tipos. Pascal y C no realizan una comprobación de tipos para sus registros variantes
con lo cual nos puede dar errores de ejecución o podemos recuperar algo que no es lo que
querÃ−amos recuperar ( Ada sÃ− ).
3.3.2 Asignación fuerte de tipos ( Strongly typed )
• Un lenguaje tiene asignación fuerte de tipos si cada identificador del lenguaje tiene asociado un
sólo tipo, y este tipo se conoce en tiempo de compilación. ( aquellos lenguajes que realizan una
vinculación estática de tipos ). Esta definición no engloba a registros variantes o uniones.
• Un lenguaje tiene asignación fuerte de tipos si los errores de tipos se detectan siempre. Esta
definición no dice si la vinculación va en tiempo de compilación ó ejecución, es una
definición más amplia.
7
• Pascal no es un lenuaje de asignación fuerte de tipos porque posee registros variantes y no realiza
una comprobación dinámica de tipos para estos registros variantes y por tanto no detecta errores
para esta estructura en cuanto a tipos.
• Ada. Resuelve el problema de los registros variantes realizando una comprobación dinámica de
tipos, pero, posee una función de librerÃ−a que nos permite extraer el contenido de cualquier zona
de memoria como un string de bits que puedo asignar a cualquier variable- > estamos escapando de la
asignación fuerte de tipos. Ada no tiene asignación fuerte de tipos.
• C. No tiene asignación fuerte de tipos ya que tiene unions. C permite funciones con parámetros
sobre los que no se realiza comprobación de tipos.
Ej:
printf("%s", 25); // No da error en tiempo de compilación pero sÃ− en tienpo de ejecución.
( No se detectan todos los errores de tipo ).
• Lenguajes con asignación fuerte de tipos: ML, Haskell realizan un comprobación fuerte de tipos.
3.3.3 Compatibilidad de Tipos (Equivalencia de tipos ).
• Si dos variables son compatibles sus valores se pueden asignar ( el valor de una se puede asignar a la
otra y viceversa ).
• Para saber si dos tipos son compatibles existen 2 métodos:
• Compatibilidad de tipos normal: Dos variables tiene una compatibilidad de tipos normal si se declaran
en el mismo lugar o en declaraciones que usan el mismo nombre de tipo.
• Compatibiliodad de Tipos Estructural: Si poseen la misma estructura.
• C.T. NOMINAL.
• Fácil de implementar ( lo único que hay que hacer es comparar el nombre de tipo de ambas
variables).
• Puede llevar una interpretación estricta:
Ej: Pascal
Type
tipo_indice = 1..100;
Var
contador: integer;
indice: tipo_indice;
Son incompatibles l ...
• Otro problema es el paso de estructuras como parámetros.
Ej: Pascal (pasar un array).
8
Procedure x (Var a:array[1..10] of integer). { Esto da un error de tipos}
• COMPATIBILIDAD DE TIPOS ESTRUCTURAL
• Se comprueba la estructura
• ¿Dos registros con igual estructura pero con nombres de campos distintos son incompatibles ?.
• ¿Dos arrays son cammpos distintos pero del mismo tipo son incompatibles ?.
[1..10] of integer
[0..9] of integer
• ¿Enumerados con igual número de elementos pero distintos nombres?
• Estos tres últimos puntos los tiene que decidir el diseñador del lenguaje, mientras que el lenguaje
tendrá que dar la respuesta.
Ej:
Type
Celsius = real;
Farenheit = real;
Var
C: Celsius;
F: Farenheit;
c:= t;
f:= c;
La compatibilidad nominal no permitirÃ−a esto.
Vamos a ver que ocure en Pascal, Ada y C:
• Pascal.
Mezcla de la C.T .Nominal y esstructural:
Type
tipo1 = array[ 1..10] of integer;
tipo2 = array[ 1..10] of integer;
tipo3 = tipo2;
9
i de tipo 1
incompatibles
j de tipo2
j de tipo2
compatibles. Aplica la equivalencia de declaración.
k de tipo3
• Ada.
Emplea C.T. Nominal en general.
Ofrece 2 constructores de tipos:
- Subtipo ( C.T.Estructurado).
- Tipo derivado.
• Tipo derivado.- Se define a partir de otro tipo. El que se está definiendo resuelta incompatibles con
el predecesor ( pero hereda todas la propiedades de éste ). Por ejemplo: Type celsius is new float;
Type farenheit is new float;
Celsius es incompatinble con float.
Farenheit es incompatible con float.
Farenheit es incompatible con celsius.
( Las constantes se tratan aparte ).
Constantes 6.0, 8.7 -> se entienden que son de un ...
• Subtipos
Subtipo natural is integer range 0.. integer'last.
Subtipo calificación is integer range -3...+3.
Natural no es incompatiblecon integer.
Calificación no es incompatible con integer.
Calificación no es incompatible con natural.
Todos los tipos tiene compatibilidad estructural: c:= n AquÃ− hay una C.T.Estructural. En compilación lo
pasa, luego en tiempo de ejecución deberá comprobar los rangos.
Ej:
10
function "**" ( i: integer; n: natural) return integer;
j**k ( k puede ser: natural, calificacción o entero.
• C: Se emplea C.T.Estructural excepto para registros y uniones ( que se emplea equivalencia de
declaración ): Typedef es un nuevo nombre paraun tipo ya existente. Hay lenguajes que permiten
definir variables de tipos anónimos.
Var
a: array[1 ..10] of integer;
b: array[1..10] of integer;
array es un tipo anónimo, a y b son tipos anonimos incompatibles
Hay lenguajes,
a,b: array[1..10] of integer;
Incompatible en Ada. Para que sean compatibles habrÃ−a que definir un tipo de manera expÃ−cita, pero es
compatible con Pascal.
3.4
Ômbito
• El ámbito de una variable es el rango de sentencias en que dicha variable es visible. Una variable es
visible en una sentencia si puede regerenciarse en la misma
• La reglas de ámbito en un lenguaje son muy importanrtes. La forma de esasa reglas va a determinar
que un identificador en un programa se asocie a una variable o se asocie a otra.
- Variables locales.
- Variables no locales. La variable no se declara en ese subprograma.
3.4.1 Ômbito Estático
• Método de vinculación de nombre de identificadores a variables no locales que ocurre en tiempo
de compilación.
• El ámbito son las variables declaradas como locales al procedimiento más la colección de todas
las variables del ámbito de subprograma antecesor que son visibles para éste. El ámbito, en este
caso, es necesitado durante la compilación.
• En Pascal, el ámbito es creado sólo por las declaraciones en los procedimientos. El ámbito
incluye las variables locales más todas las variables declaradas en los procedimientos en los cuales
el conjunto de sentencia es necesitado y más las variables declaradas en el programa principal.
• ¿Cómo se determinan los atributos de una variable en un lenguaje con ámbito
estática?(Transparencia)
• Buscar la declaración local en el subprograma 1 y si no se encuentra.
11
• Se continúa la búsqueda en el subprograma que contiene o declara al subprograma, este programa
es el padre estático de subprograma1 sino continuarÃ−a la búsqueda en todos los antepasados
estáticos de sub1
• Termina la búsqueda cuando se encuentra la declaración de x o se ha llegado a inspeccionar la
unidad mayor.
• Los estáticos pueden ocultar variables antepasadas.
• Ada - Aunque una variable esté oculta permite hacer referencia a esta variable:
Nombre_unidad_programa.nombre_variable
• Algunos lenguajes herederos permiten definir nuevos ámbitos estáticos en mitad del código
ejecutable (En éstos ámbitos puede haber nuevas variables locales).
• Bloque: Fracción de código en la que puede definirse variables locales. Da orÃ−gen a los lenguajes
estructurados en bloques.
• Pascal -> Lenguaje estructurado en bloques, todos los bloques son procedurales (procedimientos o
funciones ).
• C -> Cualquier grupo de sentencias entre llaves, las primeras sentencias de ese bloque pueden ser
declaraciones (estas son variables dinámicas de pila -> Se asigna espacio a
las variables al entrar en cada bloque
• Ada -> En cualquier punto del código puedo escribir
Declare temp: integer ; <- Temp es vble. Din. Pila
Begin
temp:=x
x:=y
y:=temp
end
• El ámbito estático proporciona un método de acceso a variables no locales que es el apropiado
en la mayorÃ−a de las ocasiones.
• Desventajas :
• Acceso a demasiados datos (todas las vbles. Declaradas en el principal son visibles en todos los
procedimientos hijos sintácticos de él )
• Los cambios pueden ser complicados
Principal principal
A
CAB
12
DCDE
B
E
Ejemplos de soluciones para cambios:
• Mover E dentro de D -> deja de tener acceso al ámbito de B con lo que podrÃ−a no funcionar.
• Mover las variables de D que necesite E al principal -> estas variables también son accesibles a A y a B
(demasiados datos ) y puede que las vbles que yo necesite es x declarado en D y la muevo al principal y
existe otra x en A habrÃ−a que renombrar las variables ( si llamamos desde D llamo a la de A y no al
principal)
Hacer cambios para que un procedimiento pueda llamar a otro enun lenguaje de ámbito
estático puede se complicado.
La tendencia de los programadores es usar más variables globales de las que necesita.
3.4.2 Ômbito Dinámico
• Son las variables declaradas localmente más las variables de todos los subprogramas que están
activos de forma concurrente.
• Lenguajes como APL.
• Se basa en la secuencia de llamadas a subprogramas
• Solamente puede determinarse el ámbito dinámico en tiempo de ejecución.
Significado de x:
• Comienza la búsqueda en las declaraciones locales.
• Se busca en las declaraciones de su padre dinámico (procedimiento que le llamó),
• sino la búsqueda prosigue con los antepasados dinámicos.
Ej. (transparencia)
. mayor->sub2->sub1
x es real, es la vble. Declarada en sub2
(tenemos que saber cual es el padre dinámico y se conoce en tiempo de ejecución)
. mayor->sub1
x es integer, es la variable declarada en mayor
• Desventajas :
• Las mismas referencias pueden tener significados diferentes en ejecuciones diferentes. (Todas las v.
Locales de todos los procedimientos son visibles en los otros procedimientos a los que llama =>
acceso a demasiados datos)
13
• Accesibilidad desde todos los subprogramas a los que se llama => menor fiabilidad
• Imposibilidad de hacer una composición de tipos estática para las v. No locales.
• Los programas son más difÃ−ciles de leer y seguir
• Ventajas :
• El subprograma llamado hereda el contexto de sus llamadores.
(Def. Ambito dinámico: Variables declaradas localmente más las variables de todos los subprogramas que
están activos de forma concurrente.)
3.4.3 Entorno de Referencia
• Variables que se pueden referenciar desde un lugar determinado.
• Conjunto de todos los identificadores visibles en dicha sentencia.
• Lenguaje de ámbito estático: Vbles. Locales + vbles. De los antepasados estáticos exceptuando
las vbles. Que se ocultan
• Lenguaje de ámbito dinámico: vbles. Locales + V. Declaradas en los antepasados dinámicos.
Variables que se pueden referenciar desde un lugar determinado.
3.5
Constantes
(Constantes con nombre)
Es un objeto al que se vincula a un valor sólo en el momento en el que se vincula el espacio.
(El valor de una constante no se puede modificar por asignación o sentencia de entrada)
• Una constante es una variable que está vinculada únicamente a un valor.
• Su valor no puede ser cambiado mediante una sentencia de asignación o cualquier otre sentenmcia.
• Las constantes son útiles para permitir una mejor legibilidad y fiabilidad.
• Otras ventajas de usar constantes es en programas que procesan un número fijado de valores de dato.
Inicialización de Variables
3.6
• La discusión de vincular valores a constantes conduce naturalmente al tópico de inicialización de
variables, porque la vinculación de un valor a una constante es el mismo proceso, excepto porque
éste es permanente.
• Es conveniente que las variables tengan un valor antes de utilizarse.
• Inicialización : Vinculación de un valor a una variable en el momento en el que se vincula el
espacio.
• C-> Puede especificarse la inicialización en el momento de la declaración
Int i=10
• Las variables estáticas se inicializan una sola vez (cuando se asigna el espacio) las variables
dinámicas de pila se inicializan también cuando se ejecuta el bloque que contiene esa
declaración.
14
Variables no Inicializadas:
C -> int i;
• Aproximaciones a las soluciones:
• Se ignora el problema (bajo responsabilidad del programador)
• No permite el uso de valores no incializados (averiguándolo en tiempo de compilación analizando
la parte derecha de todas las variables y comprobar que tienen valor)=> mayor costo
• Todas las declaraciones inicializan el espacio asignado a un valor apropiado por defecto para cada
tipo básico.
• Utilizan un valor especial para cada tipo: omega (Cuando una variables tiene el valor omega es que no
está inicializada) :I+3 > omega (i omega)
• Modula2 y PASCAL -> Ignoran el roblema
• Ada -> Los apuntadores se inicializan a NULL y se ignora el problema para el resto de tipos
• C-> Las vbles. Estáticas se inicializan a una forma apropiada de cero y se ignora el problema para el
resto de variables.
Tema 3: Datos LPR
1
13
•
15
Descargar