JERARQUIA DE OPERADORES EN C-SHARP.
Tabla de prioridades de operadores.
Lo que sigue es la lista de operadores de C, ordenados según su prioridad. En caso de que una expresión contenga más de un operador de igual prioridad, la evaluación se realizará según el orden que se indica en la columna central. Por ejemplo, si se encuentran dos operadores de desplazamiento (>> y <<), la evaluación se hará de izquierda a derecha. Pero si se encuentran dos
operadores de suma con asignación (+=), entonces la evaluación se realizará de derecha a izquierda (se evalúa primero la expresión situada más a la derecha).
Grupo de operadores Orden de
evaluación Comentarios
() [] -> . de izquierda a derecha
Este es el grupo de operadores con mayor prioridad.
! ~ ++ -- + - (tipo) * &
sizeof
de derecha a izquierda
La refundición de tipos y sizeofson operadores unarios.
* / % de izquierda
a derecha
El símbolo "%" denota el operador módulo, que produce el resto entero obtenido al dividir el primer operando por el segundo.
+ - de izquierda
a derecha
Los operadores aditivos tienen
menor prioridad que los
multiplicativos.
<< >> de izquierda a derecha
Estos son los operadores de desplazamiento bit a bit (q.v.)
< <= > >= de izquierda a derecha
== != de izquierda
a derecha
& de izquierda
a derecha
Este operador y los dos siguientes realizan operaciones lógicas bit a bit, considerando bits individuales de sus operandos.
^ de izquierda
a derecha
| de izquierda
a derecha
&& de izquierda a derecha
Este operador y el siguiente producen resultados lógicos, pero no consideran bits individuales sino el valor global del operando.
|| de izquierda
a derecha
?: de derecha a
izquierda
= += -= *= /= %= &=
^= |= <<= >>=
de derecha a izquierda
, de izquierda
a derecha
Este es el operador de menor prioridad en C. Sirve para separar una colección de expresiones, que se irán evaluando de izquierda a derecha. El resultado es el producido por la expresión situada en último lugar (más a la derecha), y tiene por tanto el tipo y valor de esta última expresión. Se emplea a veces en expresiones de control; un ejemplo sería la cláusula de iniciación de un foro la cláusula de mantenimiento de iteración de un while.
Uso de paréntesis.
Cuando el compilador genera el código que se emplea para evaluar una expresión, hace uso de la información textual de que dispone, pero no
"reconoce" la expresión, como puede hacerlo un ser humano. Las unicas reglas que se aplican son las de prioridad de operadores expuestas en la tabla
anterior. Sin embargo, C nos permite especificar sin ambigüedad el orden de evaluación deseado; esto se hace empleando paréntesis. Los paréntesis que estén anidados con más profundidad serán los primeros en evaluarse. Veáse un ejemplo.
La idea es bien sencilla: el operador paréntesis fuerza la evaluación de su contenido, elevando su prioridad con respecto a todos los demás operadores, salvo el propio operador paréntesis en el caso de que se encuentre más
profundamente anidado. Los paréntesis no estropean nada, y aseguran que el compilador entienda exactamente lo mismo que el programador. Cuando en una expresión aparecen dos o más subexpresiones entre paréntesis de igual
prioridad, se realiza la evaluación de izquierda a derecha. Véase un ejemplo.
Operador de asignación: Distinción entre = y ==.
Es muy frecuente cometer el error consistente en confundir dos operadores distintos pero de aspecto similar:
• El operador de asignación,
"="
• Y el operador de comparación,
"=="
Estos dos operadores, binarios ambos, admiten como operandos dos expresiones, y producen un resultado. Este resultado es completamente distinto:
• El operador de asignación, "=", produce como resultado el valor calculado para la expresión situada a su derecha. Por ejemplo, en valor de la expresión a = 7; es, precisamente, 7.
• Por su parte, el operador de comparación, "==", produce como resultado un valor lógico (verdadero o falso) que es verdadero si los dos operandos tienen igual valor, y falso en caso contrario. Por ejemplo,a ==
7; producirá el valor lógico verdadero (un valor numérico no nulo) si el valor de a es precisamente siete, y el valor lógico falso (un cero) si el valor de a no es siete.
Como puede apreciarse, las expresiones a = 7; y a == 7; producen resultados completamente distintos... pero existe un grave peligro. En efecto, ¿qué ocurre si se evalúa el resultado de estas expresiones desde el punto de vista lógico?
Esto es, qué resultados obtendremos si se utiliza el resultado de estas expresiones como variable de control en una sentencia if():
if( a == 7)
printf("a vale 7");
else
printf("a no vale 7);
if (a = 7)
printf("a vale 7");
else
printf("a no vale 7);
Como puede observarse, en la primera expresión el resultado será siempre correcto: a == 7 solo es no nulo si a vale 7. Pero en la segunda, el resultado de evaluar a = 7 será siempre 7. Luego pasan dos cosas:
• a siempre recibirá el valor 7, lo cual no se desea en absoluto y es un error lógico
• Además, siempre se imprimirá en pantalla "a vale 7", que puede no ser cierto; esto ocurre porque 7 es no nulo y por tanto se toma como un valor lógico verdadero.
Como decíamos, esta es una fuente de errores muy común. El compilador no puede detectarlos, porque tanto a = 7 como a == 7 son expresiones
completamente correctas. Afortunadamente, basta invertir el orden de la expresión para que el compilador detecte un error:
if( 7 == a)
printf("a vale 7");
else
printf("a no vale 7);
if (7 = a)
printf("a vale 7");
else
printf("a no vale 7);
La expresión 7 == a es válida; se tienen dos operandos para el operador de comparación. Pero la expresión 7 = a es sintácticamente incorrecta, porque 7 no es un nombre válido de variable. El compilador señala un error. Por tanto, para evitar este tipo de errores, debemos adoptar la costumbre de situar siempre las constantes a la izquierda cuando se utilice el operador "==". De este modo, si olvidamos un "=", el compilador detecta el error.
Asignaciones múltiples
Como se ha indicado, el resultado de una asignación es el valor de la expresión situada a la derecha. Esto permite escribir expresiones de la forma
a = b = c;
en donde primero se evalúa c; a continuación se asigna c a b, y por último se asigna b a a. Véase el oportuno Ejemplo.
Ejercicio.- Verificar las reglas de prioridad de operadores, empleando paréntesis para efectuar un cálculo elemental. Comprobar los resultados obtenidos tanto al emplear paréntesis como al no hacer uso de ellos.
#include <stdio.h>
void main(void) {
int cociente, a, b, c, d;
printf ("Paréntesis y prioridad de operadores\n\n");
cociente = 0;
a = 10; b = 4; c = 5; d = 1;
cociente = (a*b)/(c+d);
printf("Empleando paréntesis,cociente vale %d\n",cociente);
cociente = 0; a = 10; b = 4; c = 5; d = 1;
cociente = a*b/c+d;
printf("Sin emplear paréntesis,cociente vale %d\n",cociente);
} /*
Resultados:
Paréntesis y prioridad de operadores Empleando paréntesis,cociente vale 6 Sin emplear paréntesis,cociente vale 9
*/
Comentario.- El primer caso no tiene dificultad; los paréntesis hacen de igual prioridad los dos lados del rvalue y se evalúa la expresión de izquierda a derecha (véase el siguiente ejercicio). En el segundo caso, el operador de multiplicación y el de división tienen igual prioridad, y el operador suma tiene menor prioridad que los anteriores. Por tanto, se evalúan primero las
subexpresiones relativas a operadores de mayor prioridad. Dado que la prioridad de * y / es la misma, se evalúa de izquierda a derecha, luego se calculaa*b. Acto seguido se divide el resultado por c. Por último, a*b/c se suma con d.
Ejercicio.- Estudiar la evaluación de expresiones a igualdad de prioridades, en el caso de paréntesis. Comprobar que la evaluación se efectúa de izquierda a derecha.
#include <stdio.h>
void main(void) {
int num, cociente, a, b, c, d;
printf ("Evaluación de expresiones\n\n");
a = 10; b = 4; c = 5; d = 1; num = 0;
cociente = (num = a*b)/(num + c + d);
printf("Cociente vale %d\n", cociente);
printf("\n\nTerminación normal del programa.\n");
} /*
Salida obtenida:
Evaluación de expresiones Cociente vale 0
Terminación normal del programa.
*/
Comentario.- El resultado es 0, luego se evalúa de izquierda a derecha. Si fuera de derecha a izquierda,el denominador haría uso del valor nulo de num, y el resultado no sería cero sino 6.
Ejemplo.- Comprobar los resultados de una confusión entre el operador "=" y el operador "==".
#include <stdio.h>
void main(void) {
int a, b, c;
printf ("Confusión del operador = con el operador ==\n\n");
a = 1; b = 2; c = 3;
a = b == c;
printf("El resultado de comparar b = %d y c = %d es a = %d\n\n", b, c, a);
a = b = c;
printf("El resultado de ASIGNAR c = %d a b = %d a a es a =
%d\n\n", c, b, a);
printf("\n\nTerminación normal del programa.\n\n");
} /*
Confusión del operador = con el operador ==
El resultado de comparar b = 2 y c = 3 es a = 0 El resultado de ASIGNAR c = 3 a b = 3 a a es a = 3 Terminación normal del programa.
*/
Comentarios.- Obsérvese que 0 denota falso, y 3 denota verdadero. Por tanto, la asignación daría lugar a un valor incorrecto para a, que no sería detectado.
EJEMPLO DE ESTRUCTURA DE DATOS EN SWICHT DE C-SHARP.
switch (Referencia de C#)
La instrucción switch es una instrucción de control que selecciona una sección switch para ejecutarla desde una lista de candidatos.
Una instrucción switch incluye una o más secciones switch. Cada sección switch contiene una o más etiquetas caseseguidas de una o más instrucciones. En el ejemplo siguiente se muestra una instrucción switch simple con tres secciones switch. Cada sección switch tiene una etiqueta case, por ejemplo, case 1, y dos instrucciones.
C#
int caseSwitch = 1;
switch (caseSwitch) {
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}
Comentarios
Cada etiqueta case especifica un valor constante. La instrucción switch transfiere el control a la sección switch cuya etiqueta case coincide con el valor de la expresión switch (caseSwitch en el ejemplo). Si ninguna etiqueta case contiene un valor coincidente, el control se transfiere a la sección default, si hay alguna. Si no hay ninguna seccióndefault, no se realiza ninguna acción y el control se transfiere fuera de la instrucción switch. En el ejemplo anterior, las instrucciones en la primera sección switch se ejecutan porque case 1 coincide con el valor de caseSwitch.
Una instrucción switch puede incluir cualquier número de secciones switch y cada sección puede tener una o más etiquetas case (como se muestra en el ejemplo
siguiente de etiquetas case de una cadena). Sin embargo, las etiquetas case pueden contener el mismo valor constante.
La ejecución de la lista de instrucciones en la sección switch seleccionada comienza con la primera instrucción y continúa a lo largo de la lista de instrucciones,
normalmente hasta que se alcance una instrucción de salto, comobreak, goto case, return o throw. En este punto, el control se transfiere fuera de la instrucción switch o a otra etiqueta case.
A diferencia de C++, C# no permite que la ejecución continúe de una sección switch a la siguiente. El código siguiente genera un error.
C#
switch (caseSwitch) {
// The following switch section causes an error.
case 1:
Console.WriteLine("Case 1...");
// Add a break or other jump statement here.
case 2:
Console.WriteLine("... and/or Case 2");
break;
}
C# requiere que el final de las secciones switch, incluida la última, sea inalcanzable. Es decir, a diferencia de otros lenguajes, el código puede no pasar explícitamente a la siguiente sección switch. Aunque este requisito se cumple normalmente mediante el uso de una instrucción break, la siguiente etiqueta case también es válida, porque asegura que no se pueda llegar al final de la lista de instrucciones.
C#
case 4:
while (true)
Console.WriteLine("Endless looping. . . .");
Ejemplo
En el ejemplo siguiente se muestran los requisitos y las capacidades de una instrucción switch.
C#
class Program {
static void Main(string[] args) {
int switchExpression = 3;
switch (switchExpression) {
// A switch section can have more than one case label.
case 0:
case 1:
Console.WriteLine("Case 0 or 1");
// Most switch sections contain a jump statement, such as
// a break, goto, or return. The end of the statement list
// must be unreachable.
break;
case 2:
Console.WriteLine("Case 2");
break;
// The following line causes a warning.
Console.WriteLine("Unreachable code");
// 7 - 4 in the following line evaluates to 3.
case 7 - 4:
Console.WriteLine("Case 3");
break;
// If the value of switchExpression is not 0, 1, 2, or 3, the // default case is executed.
default:
Console.WriteLine("Default case (optional)");
// You cannot "fall through" any switch section, including
// the last one.
break;
} } }
En el último ejemplo, la variable de cadena, str, y las etiquetas case de la cadena controlan el flujo de ejecución.
C#
class SwitchTest {
static void Main() {
Console.WriteLine("Coffee sizes: 1=small 2=medium 3=large");
Console.Write("Please enter your selection: ");
string str = Console.ReadLine();
int cost = 0;
// Notice the goto statements in cases 2 and 3. The base cost of 25
// cents is added to the additional cost for the medium and large sizes.
switch (str) {
case "1":
case "small":
cost += 25;
break;
case "2":
case "medium":
cost += 25;
goto case "1";
case "3":
case "large":
cost += 50;
goto case "1";
default:
Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
break;
}
if (cost != 0) {
Console.WriteLine("Please insert {0} cents.", cost);
}
Console.WriteLine("Thank you for your business.");
} } /*
Sample Input: 2
Sample Output:
Coffee sizes: 1=small 2=medium 3=large Please enter your selection: 2
Please insert 50 cents.
Thank you for your business.
*/
OTRO EJEMPLO.
60 - Estructura condicional switch
La estructura condicional switch remplaza en algunos casos un conjunto de if.
La estructura del switch:
switch(variable) { case valor1: