Está en la página 1de 7

Unidad IV

Expresiones y Sentencias

Expresiones: clasificación y notación.

• Una expresión es la principal manera de expresar cálculos en un lenguaje de programación. Son construcciones
sintácticas que permiten al programador combinar operadores y operandos de cuya evaluación se obtiene un
valor (el valor de las expresiones depende del orden de evaluación de operadores y operandos). Es decir, es una
combinación de variables, constantes o funciones que son interpretadas según las reglas de precedencia y
asociatividad del lenguaje.
• Por lo tanto, es importante que el programador comprenda la sintaxis y la semántica de las expresiones, es decir,
además de las formas (sintaxis) de las expresiones también su significado (semántica).
• Se pueden distinguir 3 tipos (NO ES LA CLASIFICACIÓN):
◦ De valores por izquierda (l-value): expresiones de asignación, y se colocan a la izquierda del símbolo de
asignación.
◦ De valores por derecha (r-value): al evaluarlas se obtiene un valor de verdad que puede ser asignado o no.
◦ Llamadas a una función: devuelven un valor si no es tipo void.
• Las expresiones se CLASIFICAN según los operadores y operandos que contengan:
◦ Aritméticas: el propósito es resolver un cálculo aritmético. En los LP, las expresiones aritméticas consisten en
operadores, operandos, paréntesis y llamadas a funciones. Ejemplo, (x + 1). El orden de evaluación está dado por
las reglas de precedencia y asociatividad (ver más adelante)1. Los operadores pueden ser:
▪ Unarios: con un solo operando. Ejemplo: signo (x++)
▪ Binarios: con dos operandos. Ejemplo: suma, resta. (x+6)
▪ Ternarios: requieren de tres operandos. Ejemplo C, C++ el if (condición) ? TRUE: FALSE;
◦ Condicionales: tienen varias subexpresiones de las cuales exactamente una es elegida para ser evaluada, según se
cumpla una determinada condición. Ejemplo, if-then-else; el ternario de acá arriba.
◦ Relacionales: permiten determinar si una relación dada se verifica entre dos valores (mayor, menor, igual...). El
valor de una expresión relacional es booleano, excepto que no sea un tipo predefinido por el lenguaje (como es el
caso de C). La sintaxis de los operadores difiere entre los LP; por ejemplo, para desigualdad C usa !=, Ada usa /=,
Fortran usa .NE o <>.
▪ Dato copado que lo dimos en un práctico, por las dudas. JavaScript y PHP tiene dos operadores relacionales
adicionales, === y !==. Son similares a sus “==” y “!=”, pero previenen que sus operados sean coercionados.
Por ejemplo, la expresión “7” == 7 es TRUE en JavaScript, por cuando un string y un número son los
operandos de un operador relacional, el string es coercionado a un número. Sin embargo, “7” === 7 es
FALSE, por que no se aplica ninguna coerción ante este operador.
◦ Booleanas: consisten en variables booleanas, constantes booleanas, expresiones relacionales y operadores
booleanos. Se usan para determinar si un conjunto de una o más condiciones es verdadero o falso, y el resultado
de su evaluación es un valor de verdad. Los operadores booleanos usualmente son:
▪ NOT (NO): devuelve verdadero si su operando es falso y viceversa.
▪ AND (Y): devuelve verdadero si sus operandos son verdaderos.
▪ OR (O-inclusivo): devuelve verdadero si alguno de sus operandos es verdadero.
▪ XOR (O-exclusivo): devuelve falso si ambos son verdaderos.

• Notación: es la forma en que se pueden representar las expresiones. Existen tres tipos:
◦ Infija: los operadores van entre medio de los operandos. Es a la que más familiarizados estamos. La más
utilizada a la hora de codificar pero es la más compleja de traducir.
▪ EJEMPLO: (A+B)*(C-A)
◦ Prefija: se caracteriza por colocar primero los operadores (o signos) y luego los operandos. Ej. +ab. Compleja de
entender. Utilizada para un proceso de compilación más directo. Hay tres versiones usuales:
▪ Común: *(+(A, B), -(C, A)) ← Operandos separados con comas; paréntesis opcional para más legibilidad.
▪ Polaca: *+A B - C A ← Sin paréntesis, sin coma.
▪ Polaca Cambridge: (*(+ A B) (-C A)) ← Con paréntesis2.

1 En la evaluación de una expresión hay que tener en cuenta:


• Reglas de precedencia y asociatividad de operadores.
• Orden de evaluación de los operandos (Ej., de Izq. a Der. o viceversa)
• Evaluación de efectos colaterales.
• Si el LP permite sobrecarga de operadores.
2 Lisp usa Polaca Cambridge. Hay una explicación básica para esto: en Lisp, todo es una lista, incluso las expresiones; y los elementos de una lista (y sus
sublistas y subelementos, por supuesto) se separan con espacios y paréntesis.

1
◦ Postfija: inverso al caso anterior: primero los operandos y luego los operadores. Ej: ab+. Utilizada para
representación en tiempo de ejecución.
▪ Sufija: ((A, B)+, (C, A)-)* ← Paréntesis, comas.
▪ Inversa: A B + C A - *

La ventaja, tanto de postfija como de prefija, sobre infija, es que no deja lugar a ambigüedades (cosa que en infija, si no se
tienen bien claras las reglas de precedencia y asociatividad, puede ocurrir).

Estructuras de control a nivel expresión: representación y evaluación.

Evaluación de los operadores: existen dos tipos de controles a nivel expresión:


• Implícitos: son los proporcionados por el LP. Están representados por las reglas de precedencia y asociatividad de las
expresiones.
◦ Reglas de precedencia: establecen la “prioridad” de los operadores. Definen el orden en que serán evaluados los
mismos de diferente nivel de importancia (precedencia). Cuanto mayor nivel de precedencia tengan, antes serán
resueltos. La mayoría de los LP adopta este orden: Op. Aritméticos MAYOR PRECEDENCIA QUE Op.
Relacionales MAYOR PRECEDENCIA QUE Op. Booleanos.
◦ Reglas de asociatividad: definen el orden en que serán evaluados los operadores del mismo nivel de precedencia.
Por ejemplo de izquierda a derecha.
Se esperan que estas reglas sean claras y que tengan cierta uniformidad entre ellas. Hay casos especiales:
◦ En Ada no está permitido escribir varios operadores de exponenciación sin el uso de paréntesis:
▪ A**B**C → ILEGAL. Puede ser (A**B)**C -o- A**(B**C)
◦ También en Ada hay que tener cuidado con los operadores unarios:
▪ -A**B = -(A**B) no (-A)**B
◦ A**-B y A*-B son ilegales en Ada.
◦ APL es diferente, todos los operadores tienen la misma prioridad y la asociatividad es de derecha a izquierda.

• Explícitos: los especificados por el programador. Representado por algún operador que le permita al usuario del LDP
alterar el orden por defecto impuesto por el LP (generalmente los paréntesis). Tiene la desventaja que hace que las
expresiones se tornen más largas, y complicadas de seguir (esto último es subjetivo a cada programador, o sea,
disminuye Facilidad de Escritura y potencialmente puede disminuir la Legibilidad)

2
Evaluación de los operandos:
• Variables: se evalúan obteniendo su valor desde memoria.
• Constantes: algunas veces se evalúan al igual que las variables, obteniendo su valor desde la memoria; otras veces la
constante puede ser parte de las instrucciones del lenguaje máquina.
• Expresiones entre paréntesis: se evalúan los operadores y operandos dentro de los paréntesis y el valor obtenido es
usado como un operando.
Si ninguno de los operandos u operadores tiene efectos colaterales, entonces el orden de evaluación es irrelevante.

Efectos colaterales.

Una expresión tiene efecto colateral si además de devolver el resultado, modifica el entorno. El efecto colateral de una función
ocurre cuando una función cambia un parámetro de E/S o una variable global.
• Por Ej., consideremos la expresión: C + fun(C)
◦ Si fun no tiene efectos colaterales que cambien a C, entonces el orden de evaluación de los operandos no es
relevante, ya que no tiene efecto alguno en la expresión. Ahora bien, si fun cambia a C, entonces hay un efecto
colateral. Consideremos el caso de que fun retorne 10 y cambie el valor de su parámetro a 20. Ahora supongamos
que tenemos
C = 10;
B = C + fun(C)
Luego, si el valor de C es evaluado primero (en el proceso de evaluación de la expresión), su valor es 10 y el de
la expresión es 20 (valor asignado a B).
PERO si se evalúa primero la función (o sea, el segundo operando) y luego el valor de C, entonces el valor de B
va a ser 30.
Sebesta acota: nótese que las funciones en matemática no tienen efectos colaterales, por que no hay noción de “variable” en
matemática; lo mismo se aplica a lenguajes que sigan el paradigma funcional de manera pura.

Hay dos posibles soluciones al problema de la evaluación de operados y efectos colaterales:


• Deshabilitar efectos colaterales en la evaluación de funciones; que no haya parámetros de I/O en las funciones,
negando el acceso a variables globales (esto resta flexibilidad). ← O sea, que el pasaje de parámetros ser, por ejemplo,
por copia (y no por referencia).
• Imponer claramente el orden de evaluación, y “obligar” a los implementadores a que garanticen ese orden (lo que
puede afectar algunas optimizaciones que estos puedan llegar a plantear).

Transparencia referencial3.

Se dice que un programa tiene transparencia referencial si dos expresiones que tienen el mismo valor, pueden sustituirse entre
si en cualquier parte del programa, sin afectar a la acción del mismo. Es decir, que el resultado de evaluar una expresión
compuesta depende únicamente del resultado de evaluar las subexpresiones que la componen y de nada mas; no depende de la
historia del programa en ejecución ni del orden de la evaluación de las subexpresiones que la componen 4. Es decir que, el valor
de la expresión es calculado en base a sus subexpresiones y ante la misma entrada, siempre arroja la misma salida o resultado.
Por ejemplo la función cuadrado(5) cumple con la transparencia referencial (devuelve siempre 25), pero la función random(5)
no, porque devuelve un valor diferente cada vez. Es una propiedad de los LP funcionales; los LP estructurados no cumplen con
esta propiedad. Ejemplo:

result1 = (fun(a)+b) / (fun(a)-c);


temp = fun(a);
result2 = (temp+b) / (temp-c);

Si la función fun no tiene efectos colaterales, result1 y result2 serán iguales, por que la expresión asignada a ellos es
equivalente. Pero supongamos que fun tiene un efecto colateral de añadirle 1 a b o a c; entonces result1 no va a ser igual a
result2. Esto implica que los efectos colaterales violan la transparencia referencial del programa en el cuál aparece tal código.

• La transparencia es importante porque nos permite hacer modificaciones a los programas sin la necesidad de
preocuparnos de que dichas modificaciones que hagamos en un área específica, modifique indeseadamente los valores
o afecten los cálculos en otras áreas.
• Tiene la ventaja de que la semántica de los programas es mas fácil de entender: ser referencialmente transparente hace
una función equivalente a una función matemática, en términos de facilidad de comprensión.
• Los programas escritos en lenguajes funcionales puros son referencialmente transparentes. (El valor de una función
depende de sus parámetros y posiblemente de una o mas constantes globales.)

3 Mucha relación con Efectos Colaterales.


4 "El valor de la expresión es calculado en base a sus subexpresiones, y ante la misma entrada, arroja siempre la misma salida o resultado".

3
Sobrecarga de operadores.

Sobrecarga u Overloading, significa utilizar operadores aritméticos para más de un propósito. Es decir, que un mismo operador
realiza diferentes operaciones dependiendo del contexto, o sea del tipo de datos de los operandos.
• Ejemplo: En Java, el operador + se utiliza para suma de enteros, reales, y concatenación de strings.
• La sobrecarga de operadores es aceptable, siempre que no ponga en compromiso la legibilidad ni la confiabilidad.
◦ Un ejemplo de sobrecarga que puede ocasionar peligros, es la sobrecarga del operador ampersand (&) EN c.
Como un operador binario, especifica la operación lógica AND. Sin embargo, como operador unario (con una
variable como operando), el ampersand está haciendo referencia a la dirección de memoria de ese operando (o
sea, x = &y → la dirección de y será emplazada en x).
• La sobrecarga amplía las capacidades de un lenguaje, pero potencialmente puede provocar la pérdida de la detección
de errores por parte del compilador (disminución de confiabilidad) y pérdida de legibilidad.
• Esto puede evitarse con el uso de nuevos símbolos, en lugar de sobrecargar.
• Otro punto a considerar, es si el lenguaje permite definir (o redefinir) sus propios operadores sobrecargados (como es
el caso de C++, por ejemplo). Esto puede provocar que los usuarios definan operadores sin sentidos, y se pierda
legibilidad.

Evaluación en corto circuito.

La evaluación en corto circuito de una expresión es aquella en la que el resultado es determinado sin evaluar todos los
operandos y/o operadores.
• Por ejemplo: (13*a)*(b/13-1). El valor de la expresión es independiente del valor de (b/13-1) si a=0 (por motivos
aritméticos obvios, pelotudo de mierda... Ponele un 0 a a, y lo que quieras a b, y fijate cuando da). O sea, cuando a=0,
no hay necesidad de seguir evaluando el otro paréntesis.
• Otro: (a >= 0) && (b<10). Si (a >=0) es FALSO, entonces no hay necesidad evaluar (b<10) (¿Por qué? Volvé a
álgebra de primer año y preguntá cuando un AND es TRUE).
Los potenciales problemas con la Ev. en Corto Circuito se pueden ilustrar con un ejemplo, mejor:
• Supongamos que Java no usa evaluación en corto circuito. Ahora supongamos el siguiente código usando la sentencia
while, para acceder a todos los elementos de list, que es un arreglo (cuya cantidad de elementos es listlen), en busca
del elemento key:
index =0;
while ((index < listlen) && (list[index] != key))
index = index+1;
• Si la evaluación no es corto circuito, ambas expresiones relacionales en la expresión booleana del while son
evaluadas, sin importar el valor de la primera. Igual, si key no está en la lista, el programa va a terminar arrojar una
una excepción de fuera de rango. La misma iteración que tiene index=listlen va a referenciar list[listlen], lo que
causa un error de índice, por que list está declarada para tener listlen-1 como límite superior de índice.
◦ Si el lenguaje provee evaluación en corto circuito de expresiones booleanas y es usada, esto no es un problema.
En el ejemplo, una evaluación en corto circuito evaluaría el primero operando y el operador AND, y omitiría el
segundo operando en caso de que el primero sea FALSE.
◦ Un lenguaje que provee evaluación en corto circuito de expresiones booleanas pero también tiene efectos
colaterales, permite que se den errores sutiles: suponer que la evaluación en corto circuito es usada en una
expresión y parte de la expresión que contiene efectos colaterales no es evaluada; esto provocaría que el efecto
colateral ocurra solo cuando la expresión es evaluada entera: si la correctitud del programa depende de ese efecto
colateral, entonces la evaluación en corto circuito causaría un serio error.
• La gran ventaja es que se permite ahorrar tiempo en la evaluación de condiciones complejas.

Sentencias. Asignación. Asignación en modo mixto. Asignación como expresión.

Un programa esta constituido por sentencias (instrucciones) que aplican operaciones sobre datos. La asignación proporciona
un mecanismo que permite al usuario cambiar el valor de las variables. En general el operador de asignación varía entre los LP,
por ejemplo Java, C y C++ usan = mientras que Pascal y Ada usan :=. Existen distintos tipos de asignación
• Asignación simple: es la básica. Es soportada por todos los LP imperativos. Ejemplo: a = 5.
• Asignación Múltiple: no soportada por todos los LP. Es la capacidad de que en una misma sentencia se le asigne el
mismo valor a varias variables de manera simultánea. Ejemplo: a, b, c= 4.
• Asignación condicional: Perl permite una estructura del tipo ($flag ? $count1 : $count2) = 0; que es equivalente a...
if ($flag) {
$count1=0;
} else {
$count2=0;
}
• Operadores compuestos: se utilizan cuando la variable destino también aparece como operando en la expresión.
o a = a + b ES LO MISMO QUE a += b.

4
• Operadores unarios: combinan operaciones de incremento y decremento con asignación.
o a = a + 1 ES LO MISMO QUE a++.5

ASIGNACIÓN EN MODO MIXTO. Una de las cuestiones de diseño más importantes a considerar en las expresiones
aritméticas, es si un operador puede tener operandos de distintos tipos. Los lenguajes que permiten tales expresiones, que son
llamadas “expresiones en modo mixto”, deben definir convenciones para la conversión implícita de los tipos de los operandos,
por que las computadoras no tienen operaciones binarias que reciban, justamente, operandos de distintos tipos... O
directamente no permitir tales expresiones (obligar al programador a hacer una conversión de tipos explícita). Viene a colación
este tema con la asignación, por que frecuentemente puede ocurrir que el la expresión de una asignación sea de distinto tipo
que la variable que se está modificando en la asignación misma (o sea, el r-value es de un tipo, y el l-value de otro). En este
caso, el diseño debe preguntarse si el tipo de la expresión tiene que ser del mismo tipo que la variable que está siendo asignada,
o si pueden aplicarse algunas reglas de coerción en algunos casos de discordancia.
• Fortran, C, C++ y Perl usan reglas de coerción para estos casos, que son similares a las aplicadas en las expresiones
en modo mixto; esto es, que la mayoría de las mezclas de tipos de tipos es legal, y se pueden presentar dos casos:
◦ Por ampliación/promoción: a:=3; a es una variable real y 3 es una constante entera → se transforma el lado
derecho, o sea, el entero 3 se transforma en el real 3,00.
◦ Por reducción/contracción: a:=8.75; a es una variable entera y 8.75 una constante real → se realiza un
truncamiento de la parte derecha, o sea, el real 8.75 se transforma en el entero 8 (truncamiento, pérdida de
información).
• Ada no permite asignación en modo mixto (se puede forzar una conversión).
• Java y C# solo permiten las coerciones que se dan por ampliación/promoción (ver arriba), a menos que se haga una
conversión explícita.

ASIGNACIÓN COMO EXPRESIÓN. En los lenguajes basados en C, Perl y JavaScript, la sentencia de asignación produce
un resultado, que es el mismo que la valor asignado a su objetivo (l-value). Por tanto, ese resultado puede ser usado como una
expresión y como un operando en otras expresiones. En tal caso, se trata al operador de asignación de manera similar a un
operador binario, excepto que tiene efectos colaterales que cambian el operando de la izquierda. NO SE ENTIENDE UNA
MIERDA, MEJOR TOMÁ UN EJEMPLO:
while ((ch = getchar()) != EOF){}
En esa sentencia, getchar captura un carácter desde el teclado y se lo asigna a ch; el resultado o valor asignado, es comparado
con la constante EOF: si ch no es igual a EOF, entonces lo que hay entre llaves es ejecutado. Nótese en el ejemplo, que la
asignación debe estar entre paréntesis; esto se debe a que la precedencia del operador de asignación es menor que la de los
operadores relacionales (en la mayoría de los LP que permiten asignación como expresión). Sin los paréntesis, el nuevo
carácter sería comparado con EOF primero, y luego el resultado de esa comparación (booleano) sería asignado a ch.

Estructuras de control a nivel sentencia: selección, iteración, bifurcación incondicional.

Una estructura de control es una sentencia de control y las sentencias cuya ejecución ésta controlada. Las estructuras de
control permiten modificar el flujo de ejecución de las instrucciones de un programa. Por ejemplo, elegir entre varios caminos
de ejecución de acuerdo a una condición o repetir cierto numero de veces determinado grupo de sentencia. Existen mecanismos
de selección, iteración y bifurcación incondicional.

• Sentencias de selección: proporciona los medios para elegir entre dos o más caminos en la ejecución de un programa.
Se dividen en dos categorías6 7:
◦ Bidireccionales: tienen la estructura clásica if-then-else. Es decir, dada una condición (usualmente booleana), se
determina un salto a un determinado bloque de código. Potencialmente se pueden anidar selectores
bidireccionales para armar estructuras más complejas (acá viene a colación el tema de la ambigüedad, en caso de
que el lenguaje no provea directivas explícitas sobre delimitadores o palabras pregonadas que faciliten la
interpretación de las estructuras -legibilidad++-).
◦ Multidireccionales: permiten la selección de una de cualquier número de sentencias o grupo de sentencias. Se
podría decir que es una generalización de un selector (y de hecho, un bidireccional se puede construir con un
multidireccional). El formato típico es switch-case1-case2-...-caseN-default. Dada una expresión, es evaluada y
su valor es comparado con todos los casos planteados. Si se da una correspondencia, se sigue por ese flujo; de lo
contrario, se toma un camino default. (Ver imagen)

5 Nótese que en algunos lenguajes también se puede hacer "++a". Si no se encuentra combinada en una expresión, esta sentencia tiene el mismo significado
que a++ y que a=a+1; pero si sí se encuentra combinada, su significado puede variar.
6 Se puede considerar como una tercer categoría al mero "if-then", o sea, sería un unidireccional. Pero Sebesta no lo plantea, así que fue.
7 Como dato re cheto, Fortran incluye un selector de tres vías denominado "IF aritmético", que usa una expresión aritmética como control, haciendo que el
flujo pueda ir por 3 caminos distintos, dependiendo si el valor de la expresión es mayor, menor o igual que cero.

5
• Sentencias de iteración: permiten que una sentencia o grupo de sentencias se ejecute cero o mas veces. Los lenguajes
de programación brindan estructuras para representar bucles o secuencia de instrucciones que se ejecutarán de manera
iterativa. De esta manera, hacen que los programas sean mas fáciles de escribir, más legibles, menos extensos y mas
flexibles. El constructor de iteración usualmente se denomina “loop”. A nivel diseño se deben considerar dos cosas:
dónde estará ubicado el mecanismo de control (evaluación) del loop (si al principio o al final del loop, o si queda a
criterio del usuario), y cómo se controlará el loop. En base a esto, se pueden dividir los loops en tres tipos:
◦ Controladas por contador: se tiene una variable, llamada variable bucle, la cual se analiza para saber si se sigue o
no con el bucle. Se debe tener un valor inicial, uno final y un incremento especificado para la variable bucle.
Ideal para modelar bucles que se sabe, a priori, cuantas veces se desea que se repita. Es el típico caso del for en
muchos LP.
▪ Ejemplo en C: for (expr_inicial ; cond_control_final ; aumento) sentencia.8
▪ Ejemplo en Pascal: for var := valor_inicial (to|downto) valor_final do sentencia.
▪ A nivel diseño hay que considerar
• El tipo de la variable bucle (que será un escalar, excepto real).
• Si los parámetros del loop pueden modificarse dentro del propio loop (lo cual puede ocasionar resultados
inesperados, y potenciales problemas de legibilidad y -por supuesto- confiabilidad en los programas), y
en base a esto...
• … Si los parámetros del loop se evalúan en cada iteración o si solo se evalúan una vez al ingresar por
primera vez al bucle (sin posibilidad de cambio). ← Vendría, se evalúa la primera vez y dice “son X
iteraciones”, y ya queda establecido ese número de iteraciones.

◦ Controladas por condición9: útiles para cuando no se conoce con anticipación la cantidad de ingresos exactos al
bucle. Una de las cuestiones a tener en cuenta (en el diseño del LP) es si la evaluación de la condición se hace
antes (tipo Mientras CONDICIÓN=TRUE) o después de ejecutarse el bucle (tipo Repetir-Hasta que).
▪ Pascal tiene evaluación previa y posterior por separado (while-do y repeat-until).
▪ C y C++ manejan ambas con las mismas instrucciones (while-do y do-while).
▪ Java es como C, excepto que la expresión debe ser booleana.

◦ Controladas por el usuario: Algunos LP permiten sentencias iterativas controladas por el usuario, de modo que
los programadores puedan incluir controles de loop, además de los previstos por la estructura.

8 Ej. for (i=0; i<10; i++)...


9 Acá te podés hacer el gato y plantear la semántica operacional de las estructuras.

6
En Java, C y C++ existen las palabras reservadas break y continue que permiten alterar el flujo de ejecución.

• Sentencias de bifurcación incondicional: permiten transferir el control de la ejecución a alguna parte específica del
programa, principalmente a través del goto. El uso del goto es muy criticado ya que conduce a un diseño no
estructurado del programa, dificultando la legibilidad y por lo tanto el mantenimiento. También mayor dificultad en la
traducción (si el salto es muy grande o “hacia arriba”). En muchos lenguajes el uso de goto es innecesario, ya que se
puede suplantar con las distintas estructuras de control. (Java por ejemplo, en lugar de usar goto para salir de una
estructura, utiliza el break). La forma general o sintaxis de esta sentencia es GOTO etiqueta. Ejemplo: supongamos
una serie cualquiera de sentencias:
Sentencia1
Sentencia2
Sentencia3
GOTO A
B. Sentencia4
Sentencia5
A. Sentencia6
Sentencia7
En este ejemplo, después de ejecutarse la “sentencia3” nos encontramos con la sentencia “GOTO A”, la cual nos
permite bifurcar hasta la línea donde se encuentra la etiqueta “A”, y ejecuta la sentencia6. Partiendo del supuesto que
en algún lugar del programa, se ejecuten alguna vez las sentencias incluidas desde sentencia4.

Comandos protegidos.

Los comandos protegidos se utilizan principalmente en la programación concurrente (que es un problema común en el diseño
de SO) para asegurar cierta corrección durante el desarrollo del programa. Es un mecanismo para poder realizar ejecuciones no
deterministas, es decir donde son posibles varios caminos de ejecución alternativos. (O sea que no hay un camino determinado
para seguir y se pueden elegir distintas alternativas en forma concurrente).
• En una sentencia de selección if-fi: Si B, es un conjunto de condiciones y S, es un conjunto de enunciados:

Se evalúan todas las condiciones B; si más de una es verdadera se elige no-deterministicamente alguna y se ejecuta la
sentencia asociada; si ninguna es verdad tira error de ejecución.

• En una sentencia iterativa: se trata de una generalización del enunciado while:

Se evalúan todas las condiciones B; si más de una es verdadera se elige no-deterministicamente alguna y se ejecuta la
sentencia asociada. Este proceso se repite en tanto alguna sea cierta, y termina cuando todas son simultáneamente
falsas.

También podría gustarte