tipos significa que programacion operadores logicos ejemplos c++ c logical-operators short-circuiting

c++ - significa - tipos de operadores en programacion



¿Está obligado el cortocircuito a los operadores lógicos? Y orden de evaluación? (7)

¿El estándar ANSI obliga a los operadores lógicos a cortocircuitarse, en C o C ++?

Estoy confundido porque recuerdo el libro de K & R diciendo que su código no debería depender de que estas operaciones estén en cortocircuito, porque es posible que no. ¿Podría alguien señalar dónde en el estándar se dice que las operaciones lógicas siempre están en cortocircuito? Estoy interesado principalmente en C ++, una respuesta también para C sería genial.

También recuerdo haber leído (no recuerdo dónde) que la orden de evaluación no está estrictamente definida, por lo que su código no debe depender ni asumir que las funciones dentro de una expresión se ejecutarán en un orden específico: al final de una declaración todas las funciones a las que se hace referencia Habrá sido llamado, pero el compilador tiene libertad para seleccionar el orden más eficiente.

¿El estándar indica el orden de evaluación de esta expresión?

if( functionA() && functionB() && functionC() ) cout<<"Hello world";


Directamente del buen viejo K & R:

C garantiza que && y || se evalúan de izquierda a derecha; pronto veremos casos en los que esto es importante.


La evaluación de cortocircuito, y el orden de evaluación, es un estándar semántico obligatorio tanto en C como en C ++.

Si no fuera así, un código como este no sería un idioma común

char* pChar = 0; // some actions which may or may not set pChar to something if ((pChar != 0) && (*pChar != ''/0'')) { // do something useful }

La sección 6.5.13 operador lógico Y de la especificación C99 (enlace PDF) dice

(4) A diferencia del operador binario bit a bit, el operador && garantiza la evaluación de izquierda a derecha; hay un punto de secuencia después de la evaluación del primer operando. Si el primer operando se compara con 0, el segundo operando no se evalúa.

Del mismo modo, la sección 6.5.14 operador lógico O dice

(4) A diferencia del bit a bit | operador, || el operador garantiza la evaluación de izquierda a derecha; hay un punto de secuencia después de la evaluación del primer operando. Si el primer operando compara desigual a 0, el segundo operando no se evalúa.

Se puede encontrar una redacción similar en los estándares de C ++, consulte la sección 5.14 en este borrador de copia . Como las notas de los inspectores en otra respuesta, si sobrescribe && o ||, ambos operandos deben evaluarse a medida que se convierte en una llamada de función normal.


Sé muy, muy cuidadoso.

Para los tipos de POD, estos son operadores de acceso directo.

Pero si defines estos operadores para tus propias clases, no son atajos. Debido a esta diferencia semántica en su uso bajo estas diferentes circunstancias, se recomienda que no defina estos operadores.

Para el operador && y el operador || para los tipos de POD, el orden de evaluación es de izquierda a derecha (si no sería corto): para los operadores sobrecargados que defina, estos son básicamente azúcares sintácticos para definir un método y, por lo tanto, el orden de evaluación de los parámetros no está definido.


Sí, ordena eso (tanto orden de evaluación como cortocircuito). En su ejemplo, si todas las funciones devuelven verdadero, el orden de las llamadas es estrictamente desde la función A, luego la función B y luego la función C. Usado para esto como

if(ptr && ptr->value) { ... }

Lo mismo para el operador de coma:

// calls a, then b and evaluates to the value returned by b // which is used to initialize c int c = (a(), b());

Uno dice entre el operando izquierdo y derecho de && , || ,, y entre el primer y segundo / tercer operando de ?: (operador condicional) es un "punto de secuencia". Cualquier efecto secundario se evalúa completamente antes de ese punto. Entonces, esto es seguro

int a = 0; int b = (a++, a); // b initialized with 1, and a is 1

Tenga en cuenta que el operador de coma no debe confundirse con la coma sintáctica utilizada para separar cosas:

// order of calls to a and b is unspecified! function(a(), b());

El estándar de C ++ dice en 5.14/1 :

El operador && agrupa de izquierda a derecha. Los operandos se convierten implícitamente a tipo bool (cláusula 4). El resultado es verdadero si ambos operandos son verdaderos y falsos en caso contrario. A diferencia de &, && garantiza la evaluación de izquierda a derecha: el segundo operando no se evalúa si el primer operando es falso.

Y en 5.15/1 :

El || grupos de operadores de izquierda a derecha. Los operandos se convierten implícitamente a bool (cláusula 4). Devuelve verdadero si cualquiera de sus operandos es verdadero y falso de lo contrario. A diferencia de |, || garantiza la evaluación de izquierda a derecha; además, el segundo operando no se evalúa si el primer operando se evalúa como verdadero.

Dice para ambos al lado de aquellos:

El resultado es un bool. Todos los efectos secundarios de la primera expresión, excepto la destrucción de los temporales (12.2) suceden antes de que se evalúe la segunda expresión.

Además de eso, 1.9/18 dice

En la evaluación de cada una de las expresiones

  • a && b
  • a || b
  • a ? b : C
  • a , b

utilizando el significado incorporado de los operadores en estas expresiones (5.14, 5.15, 5.16, 5.18), hay un punto de secuencia después de la evaluación de la primera expresión.


Sí, se requiere orden de cortocircuito y evaluación para los operadores || y && en los estándares C y C ++.

El estándar C ++ dice (debe haber una cláusula equivalente en el estándar C):

1.9.18

En la evaluación de las siguientes expresiones

a && b a || b a ? b : c a , b

utilizando el significado incorporado de los operadores en estas expresiones, hay un punto de secuencia después de la evaluación de la primera expresión (12).

En C ++ existe una trampa adicional: el cortocircuito NO se aplica a los tipos que sobrecargan a los operadores || y && .

Nota 12: Los operadores indicados en este párrafo son los operadores incorporados, como se describe en la cláusula 5. Cuando uno de estos operadores está sobrecargado (cláusula 13) en un contexto válido, designando así una función de operador definida por el usuario, la expresión designa una invocación de función, y los operandos forman una lista de argumentos, sin un punto de secuencia implícito entre ellos.

Por lo general, no se recomienda sobrecargar estos operadores en C ++ a menos que tenga un requisito muy específico. Puede hacerlo, pero puede romper el comportamiento esperado en el código de otras personas, especialmente si estos operadores se usan indirectamente a través de la creación de instancias de plantillas con el tipo sobrecargando estos operadores.



Su pregunta se reduce a la precedencia y asociatividad del operador de C ++ . Básicamente, en expresiones con operadores múltiples y sin paréntesis, el compilador construye el árbol de expresiones siguiendo estas reglas.

Para la precedencia, cuando tienes algo como A op1 B op2 C , puedes agrupar las cosas como (A op1 B) op2 C o A op1 (B op2 C) . Si op1 tiene mayor prioridad que op2 , obtendrá la primera expresión. De lo contrario, obtendrás el segundo.

Para la asociatividad, cuando tienes algo como A op B op C , puedes agrupar de nuevo como (A op B) op C o A op (B op C) . Si op ha dejado la asociatividad, terminamos con la primera expresión. Si tiene una asociatividad correcta, terminamos con la segunda. Esto también funciona para operadores en el mismo nivel de precedencia.

En este caso particular, && tiene mayor prioridad que || , por lo que la expresión se evaluará como (a != "" && it == seqMap.end()) || isEven (a != "" && it == seqMap.end()) || isEven .

El orden en sí es "de izquierda a derecha" en la forma del árbol de expresiones. Por lo tanto, primero evaluaremos a != "" && it == seqMap.end() . Si es verdad, toda la expresión es verdadera, de lo contrario, vamos a isEven . El procedimiento se repite recursivamente dentro de la subexpresión izquierda, por supuesto.

Datos interesantes, pero el concepto de precedencia tiene sus raíces en la notación matemática. Lo mismo ocurre en a*b + c , donde * tiene una precedencia mayor que + .

Aún más interesante / oscuro, para una expresión sin oposición A1 op1 A2 op2 ... opn-1 An , donde todos los operadores tienen la misma precedencia, el número de árboles de expresión binaria que podríamos formar está dado por los llamados números catalanes . Para n grande, estos crecen extremadamente rápido. re