4.9.6 Operador Condicional
§1 Sinopsis
El operador condicional es el único operador ternario de la gramática C++ y sirve para tomar decisiones. Proporciona un resultado entre dos posibilidades en función de una condición.
Nota: Puede afirmarse que este operador ha hecho fortuna, ya que existe con la misma sintaxis e idéntico comportamiento, en multitud de otros lenguajes de programación.
§2 Sintaxis
expresion-relacional ? expr1 : expr2
§3 Comentario
El operador condicional ? : produce un resultado. En la expresión E1 ? E2 : E3, E1 es una expresión relacional ( 4.9.12) que se evalúa primero. Si el resultado es cierto, entonces se evalúa E2 y este es el resultado. En caso contrario (si E1 resulta falso), entonces se evalúa E3 y este es el resultado. Observe que si la premisa E1 es cierta, entonces no llega a evaluarse la expresión E3.
§3.1 El operador ? : puede usarse para sustituir ciertas sentencias del tipo if-then-else,
aunque puede conducir a expresiones más compactas que las correspondientes if...else. En el ejemplo que sigue, a y
se le asigna el valor 100:
x = 10;
y = x > 9 ? 100 : 200;
§3.2 No es necesario poner paréntesis en la primera expresión (E1), ya que la precedencia ( 4.9.0a) de ? : es muy baja (justamente sobre la asignación = ). De todos modos, es aconsejable ponerlos por legibilidad.
y = (x > 9)? 100 : 200;
§3.3 En caso de que E1 no sea una expresión relacional, debe ser un escalar reducible a un
booleano (Conversión de tipos
3.2.1b). Por ejemplo es válido:
int y = 6 ? 7: 8;
aunque en este caso el resultado sería siempre y == 7 (el int 6 se se traduce en el booleano true).
§3.4 En ocasiones se aprovechan los efectos laterales
( 4.9) del operador para producir un
resultado. Ejemplo:
++x ? ++y : --z;
El compilador GNU cpp permite la ausencia del segundo operando en este tipo de expresiones. Por ejemplo, es válido:
x ? : z; // E1
El resultado de esta expresión es el valor de x si este es distinto de cero, y z en caso contrario. Por consiguiente, es equivalente a:
x ? x : z; // E2
El manual informa que este tipo de expresiones solo son de utilidad en caso de que la evaluación de x tenga efectos laterales (por ejemplo, que sea utilizada como argumento en una función), en cuyo caso la expresión E2 tendría efecto lateral doble si x es distinto de cero. La omisión del segundo operador en E1 evitaría esta computación indeseada y dejaría el valor previamente computado sin que se produzca un doble efecto.
§4 E2 y E3 deben seguir las reglas siguientes:
- Si E2 y E3 son de tipos distintos, se realiza una conversión de tipo estándar, de forma que el resultado será siempre del mismo tipo, con independencia de E1.
- Si E2 y E3 son de tipos unión o estructuras compatibles. El resultado es una unión o estructura del tipo de E2 y E3.
- Si E2 y E3 son de tipo void, el resultado es void.
- Ambos operandos son punteros a versiones cualificadas o no cualificadas de tipos compatibles. El resultado es un puntero a cualquiera de los tipos de ambos operandos.
- Un operando es un puntero y el otro es un puntero nulo. El resultado es un puntero que puede señalar a un tipo del primero o del segundo operando.
- Un operando es un puntero a un objeto o tipo incompleto, y el otro es un puntero a una versión cualificada o no cualificada de void. El tipo resultante es el del puntero distinto de void.
§5 Ejemplos
§5.1 Suponiendo que z e y sean Lvalues, las siguientes expresiones son equivalentes:
(x ? y : z) = 10;
(x ? y = 10 : (z = 10));
§5.2 El bucle que sigue imprime n elementos de una matriz, 10 por línea, con cada columna separada
por un espacio y con cada línea terminada por un NL (nueva línea), incluida la última.
for (i = 0; i < n; i++)
printf ("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');
§5.3 Ejemplo:
printf ( "Tienes %d item%s.\n", n, n==1 ? "" : "s");
§5.4 Ejemplo:
#include <iostream.h>
#include <time.h>
int main(void) { // ============
time_t t;
time(&t);
struct tm* petm = localtime(&t);
long dgt = _timezone/60;
cout << "Diferencia hora local con Greenwich = "
<< abs(dgt) << " minutos " <<
(dgt == 0 ? "\n" : (dgt < 0 ? "adelanto\n" : "atraso\n"));
cout << "Horario: " << (petm->tm_isdst ? "Verano" : "Invierno") << endl;
}
Salida:
Diferencia hora local con Greenwich = 60 minutos adelanto
Horario: Verano