2009-07-04 16 views
44

Leí en alguna parte que el operador ?: en C es ligeramente diferente en C++, que hay algún código fuente que funciona de manera diferente en ambos idiomas. Lamentablemente, no puedo encontrar el texto en ninguna parte. ¿Alguien sabe cuál es esta diferencia?Diferencias de operador condicional entre C y C++

Respuesta

67

El operador condicional en C++ puede devolver un lvalue, mientras que C no permite una funcionalidad similar.Por lo tanto, la siguiente es social en C++:

(true ? a : b) = 1; 

Para replicar esto en C, que tendría que recurrir a if/else, o hacer frente a las referencias directamente:

*(true ? &a : &b) = 1; 

También en C++, ?: y = operadores tienen equal precedence and group right-to-left, tal que:

(true ? a = 1 : b = 2); 

es válida código C++, pero generará un error en C sin paréntesis alrededor de la última correo xpression:

(true ? a = 1 : (b = 2)); 
+19

En C puede escribir * (true? & A: & b) = 1 en su lugar – finnw

+0

@finnw: útil. actualizado mi respuesta en consecuencia. – goldPseudo

+5

La segunda diferencia no es sobre el orden de las operaciones, se trata de la precedencia del operador. – Barmar

22

La principal diferencia práctica es que en C, la evaluación de?: Nunca puede dar como resultado un valor de l donde, como en C++, puede hacerlo.

Existen otras diferencias en su definición que tienen pocas consecuencias prácticas. En C++, el primer operando se convierte en bool, en C se compara con 0. Esto es análogo a la diferencia en la definición de ==,! =, Etc. entre C y C++.

También hay reglas más complejas en C++ para deducir el tipo de una expresión?: Basada en los tipos del 2º y 3er operandos. Esto refleja la posibilidad de conversiones implícitas definidas por el usuario en C++.

Código de ejemplo. C++ válido; C. inválida

extern int h(int p, int q); 

int g(int x) 
{ 
     int a = 3, b = 5; 

     (x ? a : b) = 7; 

     return h(a, b); 
} 

gcc genera el error: "error: lvalue no válida en cesión" al compilar como C, pero el código se compila sin error al compilar como C++.

Editar: Aunque:? No puede devolver un valor L en C, tal vez sorprendentemente la gramática para:? Es:

conditional-expression: 
    logical-OR-expression 
    logical-OR-expression ? expression : conditional-expression 

Esto significa que a ? b : c = d análisis sintáctico como (a ? b : c) = d a pesar de que (debido a la regla 'no un valor l') esto no puede dar como resultado una expresión válida.

C++ cambia la gramática a esto:

conditional-expression: 
    logical-or-expression 
    logical-or-expression ? expression : assignment-expression 

mientras que la extensión para permitir condicional-expresión para ser un valor L en algunas situaciones habría hecho a ? b : c = d válida sin el cambio de la gramática, los nuevos medios de cambio de la gramática que la expresión ahora es válida pero con el diferente significado de a ? b : (c = d).

Aunque no tengo ninguna evidencia para ello, mi suposición de que como el cambio de gramática no podía romper la compatibilidad con el código C existente, era más probable que la nueva gramática produjera menos sorpresas con expresiones como:

make_zero ? z = 0 : z = 1; 
+0

La parte de la respuesta que describe C parse es incorrecta. En gramática C, el operador LHS de '=' no puede contener un operador '?:' No entre paréntesis. El análisis '(a? B: c) = d' sugerido no es realmente posible. En C gramática 'a? b: la expresión c = d' no es para nada analizable. Cualquier compilador que lo interprete como '(a? B: c) = d' lo hace bajo su propio riesgo. (Este suele ser el caso en los compiladores híbridos C/C++ que intentan unificar las gramáticas C y C++). Formalmente, no hay ningún problema, ya que el código no válido sigue siendo rechazado. Pero el mensaje "not an lvalue" es engañoso. – AnT

+0

En C, 'a? b: c = d' es simplemente un galimatías sintáctico, una secuencia de tokens no analizables. No es una expresión. Afirmar que asigna a un valor no-l es incorrecto, ya que no hay "asignación" aquí. – AnT

Cuestiones relacionadas