varias sentencia que programacion lenguaje for estructuras estructura else ejemplos decision control condiciones ciclo c++ if-statement comma

c++ - sentencia - que es if else en programacion



¿Cuál es la ventaja de las comas en una declaración condicional? (7)

Cambiando un poco su ejemplo, supongamos que fue esto

if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )

(tenga en cuenta el = lugar de == ). En este caso, las comas garantizan un orden de evaluación de izquierda a derecha. En contraste, con esto

if ( thisMustBeTrue(f(5), f(6)) )

no sabe si se llama f(5) antes o después de f(6) .

Más formalmente, las comas le permiten escribir una secuencia de expresiones (a,b,c) de la misma manera que puede usar ; escribir una secuencia de declaraciones a; b; c; a; b; c; . Y justo como a ; crea un punto de secuencia (final de la expresión completa) también lo hace una coma. Solo los puntos de secuencia rigen el orden de evaluación, vea esta publicación .

Pero, por supuesto, en este caso, realmente escribirías esto

a = f(5); b = f(6); if ( thisMustBeTrue(a, b) )

Entonces, ¿cuándo es una secuencia de expresiones separadas por comas preferible a a ; secuencia separada de declaraciones? Casi nunca diría. Quizás en una macro cuando desea que el reemplazo del lado derecho sea una sola expresión.

Podemos escribir una declaración if como

if (a == 5, b == 6, ... , thisMustBeTrue)

y solo la última condición debe ser satisfactoria para ingresar al cuerpo if .

¿Por qué está permitido?


Lo que sigue es un poco exagerado, dependiendo de qué tan desviado sea.

Considere la situación en la que una función devuelve un valor modificando un parámetro pasado por referencia o mediante un puntero (tal vez de una biblioteca mal diseñada, o para asegurarse de que este valor no se ignore al no ser asignado después de regresar, lo que sea).

void calculateValue(FooType &result) {/*...*/}

Entonces, ¿cómo se utilizan las declaraciones condicionales que dependen del result ?

Puede declarar la variable que se modificará y luego verificarla con un if:

FooType result; calculateValue(result); if (result.isBared()) { //... }

Esto podría acortarse a

FooType result; if (calculateValue(result) , result.isBared()) { //... }

Lo que realmente no vale la pena. Sin embargo , para los bucles while podría haber algunas pequeñas ventajas. Si calculateValue debería / puede llamarse hasta que el resultado ya no sea bar ''d, tendríamos algo como:

FooType result; calculateValue(result); //[1] Duplicated code, see [2] while (result.isBared()) { //... possibly many lines //separating the two places where result is modified and tested //How do you prevent someone coming after you and adds a `continue` //here which prevents result to be updated in the and of the loop? calculateValue(result); //[2] Duplicated code, see [1] }

y podría condensarse en:

FooType result; while (calculateValue(result) , result.isBared()) { //all your (possibly numerous) code lines go here }

De esta manera, el código para actualizar el result está en un solo lugar y está cerca de la línea donde se verifican sus condiciones.

puede no estar relacionado: otra razón por la cual las variables podrían actualizarse mediante el paso de parámetros es que la función necesita devolver el código de error además de modificar / devolver el valor calculado. En este caso:

ErrorType fallibleCalculation(FooType &result) {/*...*/}

entonces

FooType result; ErrorType error; while (error = fallibleCalculation(result) , (Success==error && result.isBared())) { //... }

pero como se señala en los comentarios, también puede hacer esto sin la coma:

FooType result; ErrorType error; while (Success == fallibleCalculation(result) && result.isBared()) { //... }


Ninguno en absoluto. Las comparaciones en a en ese código son completamente redundantes.


No hay ninguna ventaja : el operador de coma es simplemente una expresión con el tipo de la última expresión en su lista de expresiones y una instrucción if evalúa una expresión booleana.

if(<expr>) { ... } with type of <expr> boolean

Es un operador extraño cierto, pero no tiene magia, excepto que confunde listas de expresiones con listas de argumentos en llamadas a funciones.

foo(<args>) with <args> := [<expr>[, <expr>]*]

Tenga en cuenta que en la lista de argumentos, la coma se une más fuerte a los argumentos de separación.


Para una declaración if , no tiene sentido poner algo en una expresión de coma en lugar de afuera.

Para una instrucción while , al poner una expresión de coma en la condición se ejecuta la primera parte, ya sea al ingresar al bucle o al bucle. Eso no se puede replicar fácilmente sin duplicación de código.

Entonces, ¿qué tal como do ... while declaración? Allí solo tenemos que preocuparnos por el bucle en sí, ¿verdad? Resulta que ni siquiera aquí una expresión de coma se puede reemplazar de forma segura moviendo la primera parte al bucle.

Por un lado, los destructores de variables en el cuerpo del bucle ya no se habrán ejecutado, lo que podría marcar la diferencia. Por otro lado, cualquier instrucción de continue dentro del bucle alcanzará la primera parte de la expresión de coma solo cuando esté en la condición y no en el cuerpo del bucle.


Mi pregunta es ¿cuál es la ventaja de las comas en la declaración if o while ? ¿Por qué está permitido?

Existe porque las declaraciones y expresiones son cosas diferentes en C. Una expresión compuesta es una construcción que se entiende desde la teoría (y algunos otros lenguajes) y que faltaría sin haberla agregado en forma de coma. Su uso en la declaración for fue la justificación original de por qué lo necesitaban.

Pero, al hacer que el lenguaje sea más completo desde un punto de vista teórico sólido, más tarde encuentra usos que nadie planeó. El C ++ temprano era un traductor que generaba C como su salida, y tener una expresión secuencial era absolutamente esencial para permitir que las funciones en línea generaran realmente una lógica "en línea" en el código C.

Eso incluye cualquier lugar donde aparezca la expresión, incluida la condición de una instrucción if .

Del mismo modo, se ha utilizado en macros "interesantes". Y tanto como C ++ eliminó las macros al proporcionar funciones en línea, hasta los compiladores hasta x11 encontraron el bucle de rango Boost FOREACH (eventualmente, una emulación de la función agregada al lenguaje en x11) muy útil, y eso fue un conjunto diabólicamente inteligente de macros que involucraba al operador de coma.

(Hmm, la versión actual se expande en múltiples declaraciones usando if / else encadenado, en lugar de agruparlo todo en un solo while ).

Ahora, hay otra forma de poner cualquier declaración en una expresión (lambdas), por lo que el futuro negocio loco de macros que emulan características de lenguaje aún más nuevas o lenguajes incrustados específicos de dominio podría no necesitar usar eso nunca más.

Entonces, no escriba código como ese. A menos que sea claro y, de hecho, más simple que escribir funciones auxiliares o dividirse en varias declaraciones.

Pero puede ser justo para una macro que desea usar fácilmente en un lugar y ese lugar está dentro de los parentes de un if o while . Eso podría justificarse en un lenguaje específico de dominio alojado dentro del código fuente de C ++, o en una función de emulación de lenguaje como (quizás) una alternativa al manejo de excepciones utilizado en un sistema embebido en tiempo real.

En resumen, no tiene un buen uso normal. Pero está ahí para completar y nunca se sabe cuándo alguien lo encontrará útil.


En resumen: aunque es legal hacerlo, generalmente no tiene sentido usar el operador de coma en la condición parte de una declaración if o while (EDITAR: aunque esto último a veces puede ser útil como explica el usuario 5534870 en su respuesta) .

Una explicación más elaborada: además de su función sintáctica (por ejemplo, separar elementos en listas de inicializadores, declaraciones de variables o llamadas a funciones / declaraciones), en C y C ++, el , también puede ser un operador normal como, por ejemplo, + , y así puede ser se usa en todas partes, donde se permite una expresión (en C ++ incluso puede sobrecargarla).
La diferencia con la mayoría de los otros operadores es que, aunque se evalúan ambos lados, no combina las salidas de las expresiones izquierda y derecha de ninguna manera, sino que solo devuelve la correcta.
Se introdujo porque alguien (probablemente Dennis Ritchie) decidió por alguna razón que C requería una sintaxis para escribir dos (o más) expresiones no relacionadas en una posición, donde normalmente solo se podía escribir una sola expresión.

Ahora, la condición de una declaración if es (entre otros) tal lugar y, en consecuencia, también puede usar el operador , allí, ¡si tiene sentido hacerlo o no, es una pregunta completamente diferente! En particular, y diferente de, por ejemplo, llamadas a funciones o declaraciones de variables, la coma no tiene un significado especial allí, por lo que tiene lo que siempre hace: evalúa las expresiones a la izquierda y a la derecha, pero solo devuelve el resultado de la derecha, que luego es utilizado por la declaración if .

Los únicos dos puntos en los que puedo pensar en este momento, donde usar el operador ( no sobrecargado ) tiene sentido son:

  1. Si desea incrementar múltiples iteradores en la cabeza de un bucle for :

    for ( ... ; ... ; ++i1, ++i2){ *i2=*i1; }

  2. Si desea evaluar más de una expresión en una función constexpr de C ++ 11.

Para repetir esto una vez más: Usar el operador de coma en una declaración if o while , tal como lo mostró en su ejemplo, no es algo sensato de hacer. Es solo otro ejemplo en el que las sintaxis de lenguaje de C y C ++ le permiten escribir código, que no se comporta de la manera que uno, a primera vista, lo esperaría. Hay muchos más....