El fin de verificar las condiciones en C

0

Pregunta

Por lo que estuve leyendo sobre el orden de los distintos operadores, y he leído que && tiene mayor importancia que el || y se evalúe la tarde (fuente). Entonces alguien le hace una pregunta acerca de lo que esta pieza de código de impresión:

#include <stdio.h>
int main(){
    int a=0, b=0, c=0, d=0;
    if(a++>0 || ++b==1 || c--<=0 && d++>c--){
        printf("if\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    else{
        printf("else\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    return 0;
}

Y yo que pensaba que el c-- <= 0 && d++ > c-- evalúe la primera, que es verdadero en total. después de que el proceso, c será igual a -2 y d sería igual a 1. Entonces se podría iniciar la comprobación de la izquierda lado, la evaluación de a++ > 0 || ++b == 1 lo cual es cierto, a sería de 1 en la final y b es de 1 en la condición y después de eso. por lo que el total de la condición sería true || true y es verdad, así que vamos a imprimir:

if
a:1
b:1
c:-2
d:1

Sí? Al parecer, no. Lo he probado con GCC (Mingw) en mi sistema (Windows 10), y con un compilador (este) y tanto en la edición impresa:

if
a:1
b:1
c:0
d:0

He cambiado la condición en esto: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) pero la salida es exactamente lo mismo en ambos lugares. Hay algo que no me preste atención a? O se trata de algo así como un error? Casi parece como que || y && tienen la misma prioridad y la cosa entera es evaluada desde el lado izquierdo, y corto-circuitos se produce y otras cosas. Si puedo cambiar el ++b==1 parte en ++b==0, entonces la salida es el mismo como lo había predicho.
Gracias de antemano por cualquier tipo de ayuda :)

1

Mejor respuesta

4

La expresión en esta pregunta:

if(a++>0 || ++b==1 || c--<=0 && d++>c--)

es un ejemplo clásico de una horrible expresión, tremendamente realista y práctico, y punishingly difícil de entender, que sin embargo hace un buen trabajo de ilustración de un super punto importante: la prioridad no es el mismo que el orden de evaluación.

Lo precedencia realmente nos dice es cómo los operadores están conectados con sus operandos. Así que, dado que la expresión simplificada

A || B || C && D

que dos subexpresiones que hacer la primera ||y la segunda ||y el && en realidad vincular y operar? Si usted es un compilador de escritor, responder a estas preguntas mediante la construcción de un "árbol de análisis", que de manera explícita que la subexpresión(s) con las que ir a los operadores.

Por tanto, dada la expresión A || B || C && D¿el árbol de análisis de la expresión de este aspecto:

        &&
       /  \
     ||    D
    /  \
  ||    C
 /  \
A    B

o como esta:

  ||
 /  \
A    ||
    /  \
   B    &&
       /  \
      C    D

o como esta:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Para responder esta pregunta, necesitamos saber no sólo que la prioridad de && es superior a la de ||pero también que || a la izquierda asociativa. Teniendo en cuenta estos hechos, la expresión

A || B || C && D

se analiza como si hubiera sido escrito

(A || B) || (C && D)

y, por lo tanto, los resultados en el tercero de los tres candidatos a analizar los árboles me mostró:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Pero ahora estamos en una posición para ver realmente cómo el "cortocircuito" el comportamiento de la || y && los operadores se van a aplicar. Que "de arriba" || se va a evaluar su mano izquierda y, a continuación, si es falso, también evaluar el lado derecho. Asimismo, la menor || se va a evaluar su mano izquierda. Así que, no importa qué, A se va a poner evalúan primero. Para la expresión en la pregunta original, que corresponde a a++ > 0.

Ahora, a++>0 es falso, por lo que vamos a tener que evaluar B, que es ++b == 1. Ahora, eso es cierto, por lo que el resultado de la primera || es "verdadero".

Así, el resultado de la segunda (parte superior) || el operador también es "verdadero".

De modo que el lado derecho de la parte superior || el operador no tiene que ser evaluado en todos.

De manera que toda la subexpresión que contiene && no serán evaluados en todos.

Así que a pesar de && tenía la prioridad más alta, que terminó siendo considerada la última, y (ya las cosas a la izquierda involucrados || y era cierto) no terminan siendo evaluados en todos.

La línea de fondo, como empecé diciendo, es que la prioridad no determina el orden de evaluación.

También, si no fue dicho en otras ocasiones, esta garantizado, de izquierda a derecha comportamiento es sólo garantizada por el || y && los operadores (y, de una manera diferente, para el ternario ?: el operador). Si la expresión había sido

A + B + C * D

podría no haber sido cierto que, como he dicho antes, "no importa qué, A se va a poner evalúan primero". Para los operadores aritméticos como + y *no hay forma de saber si el lado izquierdo o el lado derecho que se va a poner evalúan primero.

2021-11-24 12:41:40

Completa y Racional. Muchas gracias de nuevo.
III_phr

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................