¿Cómo funciona exactamente el operador ?: en C?

10

Tengo una pregunta, cómo funciona el compilador en el siguiente código:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

No estoy seguro de por qué el resultado es d = 11.

J0S
fuente
1
¿Por qué no estás seguro? ¿Qué más esperarías y por qué?
Gerhardh
2
No recuerdo la semántica precisa involucrada, pero puede estar observando un comportamiento indefinido.
chepner
3
No, @chepner, hay un punto de secuencia después de evaluar la condición de un ternario, antes de evaluar la alternativa seleccionada. Eso evita el vector UB, supongo que estás pensando.
John Bollinger
Sí, no estoy seguro de dónde pensé que el compilador podría elegir.
Chepner

Respuestas:

6

En int d = (b == c++) ? (c+1) : (c-1);:

  • El valor de c++es el valor actual de c11. Por separado, cse incrementa a 12.
  • b == 11 es falso, ya que b es 12.
  • Como (b == c++)es falso, (c-1)se usa. Además, el incremento dec a 12 debe completarse en este punto.
  • Como ces 12, c-1es 11.
  • d se inicializa a ese valor, 11.
Eric Postpischil
fuente
5

De acuerdo con el Estándar C (6.5.15 Operador condicional)

4 Se evalúa el primer operando; hay un punto de secuencia entre su evaluación y la evaluación del segundo o tercer operando (lo que se evalúe). El segundo operando se evalúa solo si el primero se compara desigual a 0; el tercer operando se evalúa solo si el primero se compara igual a 0; el resultado es el valor del segundo o tercer operando (el que se evalúe), convertido al tipo que se describe a continuación.110)

Entonces, en la expresión inicial de esta declaración

int d = (b == c++) ? (c+1) : (c-1);

la variable bse compara con el valor de la variablec porque el operador posterior al incremento devuelve el valor de su operando antes de incrementarlo.

Como los valores no son iguales entre sí (b se establece en 12 mientras cse establece en 11), entonces la sub-expresión(c-1) se evalúa la subexpresión.

Según la cita, hay un punto de secuencia después de la evaluación de la condición del operador. Significa que después de la evaluación de la condición ctiene el valor 12después de aplicar el operador de incremento posterior a la variable c. Como resultado, la variable d se inicializa por el valor 1(12 - 1 ).

Vlad de Moscú
fuente
2
La única respuesta correcta: este caso específico debe responderse mencionando el punto de secuencia ?:. Porque normalmente en C, la combinación ++con otras operaciones en el mismo operando es un comportamiento indefinido. Y este código solo funciona de manera predecible porque ?:tiene varias reglas especiales de copos de nieve.
Lundin
4

Debido a que la condición es falsa, por lo tanto, el falsecaso sucederá: c-1pero desde que incrementóc la condición en c++, por clo tanto, es ahora 12. El resultado es 12 - 1, que es 11.

EDITAR: Lo que OP no entendió fue el incremento de publicación.

Entonces, lo que realmente sucede es así:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}
Eraklon
fuente
1
Creo que el OP se refiere al orden de las operaciones, dado el c++en la condición. La condición es falsa, pero entonces el orginal valor de cse utiliza para calcular c - 1, no la versión incrementa.
chepner
1
Pensé que desde 12 == 11 + 1 es cierto ...
J0S
Pero eso no es cierto ya que se utiliza el nuevo valor de c o me estoy perdiendo el punto de los suyos?
Eraklon
Creo que podría haber un malentendido entre c++y++c
ChatterOne
@ N00b c++es el operador posterior al incremento. El valor de c++es 11, con el efecto secundario de hacer c == 12. ++ctendría el valor de 12.
chepner
4

Traducido a una declaración if regular, su código se vería así:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

La pista aquí es que c se incrementa después de que se verifica la condición. Entonces ingresa el elseestado pero c ya tiene el valor 12 allí.

Odiseo
fuente
1

Consulte Operador ternario.

Sintaxis

condición? value_if_true: value_if_false

Entonces escribiste

int d = (b == c++) ? (c+1) : (c-1);

En esta situación, el resultado será 11 porque, después de verificaciones, el valor 'c' aumenta (c + 1 = 12) y solo después establece el valor 'd' como c (12) -1, que es 11.

Si usaste, por ejemplo:

int d = (b == ++c) ? (c+1) : (c-1);

El valor "c" se incrementaría antes de verificar el enunciado, por lo que sería verdadero y el valor "d" sería c (12) +1, que es 13.

Neto Costa
fuente