2010-12-08 14 views
7

Nos metimos en un código como este en nuestra base de códigos ... lo que me preocupó.¿Devuelve el valor del alcance local?

int foo(int a); // Forward declaration. 

int baz() { 
    int result = { 
     int a = dosomestuff(); 
     foo(a); 
    } ? 0 : -1; 
    return result; 
} 
  1. está bien definido el comportamiento de este código?
  2. ¿Funcionará realmente, esa variable result se carga con 0 o -1 dependiendo del valor de retorno de foo(a)?

Por interés: el código no fue escrito originalmente como eso - sin embargo, es lo que me imagino esta macro de aspecto inocente se extenderá a ...

int foo(int a); // Forward declaration. 

#define BAR() { int a = dosomestuff(); foo(a); } 

int baz() { 
    int result = BAR() ? 0 : -1; 
    return result; 
} 
+0

Yow. ¿Qué compilador de C acepta eso? gcc ciertamente no. – aschepler

+1

@aschepler: irónicamente, parece que GCC es el * único * compilador que lo acepta. Ver la respuesta de Michael Burr. –

+0

El compilador es VisualDSP ++ por Analog Devices. Probablemente pediré ayuda sobre esto mañana. –

Respuesta

11

Esta es una extensión de GCC para C llamado 'expresiones de los estados': http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

La clave es que una expresión instrucción devuelve la última cosa que hace que el valor de la expresión:

El Lo último en la declaración compuesta debe ser una expresión seguida de un punto y coma; el valor de esta subexpresión sirve como el valor de la construcción completa.

En su ejemplo, eso sería lo que devuelva foo(a).

Sin embargo, el bloque debe incluirse en parens para que GCC acepte la sintaxis.

int foo(); // Forward declaration. 

int baz() { 
    int result = ({ 
     int a = dosomestuff(); 
     foo(a); 
    }) ? 0 : -1; 
    return result; 
} 

No tengo conocimiento de ningún otro compilador que admita esto.

+0

Llegó primero. Como un FYI aquí está el enlace a todas las extensiones de GCC C http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions –

+4

En este caso específico, una forma más portátil de escribirlo probablemente estar en orden. Considere 'int result = foo (dosomestuff())? 0: -1; ' –

+1

@ André: definitivamente. El caso de uso para expresiones de enunciados parece ayudar a crear macros o macros 'con seguridad de parámetros' que se repiten. Creo que hay muy pocas razones para usarlos en las funciones normales. –

0

Porque es una tipo simple no puntero, se devolverá el valor exacto y, por lo tanto, se definirá el comportamiento de devolución. Ese bloque es ... realmente extraño, y estoy sorprendido de que haya un compilador de C que no se ahogue allí.

1

No conozco un solo compilador que acepte eso. Además, sería mejor que hicieras esto:

int foo(); 
int dosomestuff(); 

int baz() 
{ 
    int result = foo(dosomestuff()) ? 0 : -1; 
    return result; 
} 
4

Tendría que consultar la documentación del compilador. Esta construcción no está permitida en C estándar o en C++ estándar.

Sin embargo, es trivial limpiar esto, p.

int baz() 
{ 
    int result; 
    { 
     int a = dosomestuff(); 
     result = foo(a)? 0: -1; 
    } 
    return result; 
} 
+0

Sí, sé que la función puede hacerse mucho más corta. Solo estoy dando un ejemplo del cambio mínimo necesario para que sea compatible con el estándar. Esta conversión es puramente mecánica, por lo que puede usarse en CUALQUIER código que use esta construcción. –

1

No es estándar C++.

En C++ estándar, escribir

bool baz() { return !foo(dosomestuff()); } 

Eso es todo.

+0

Eso cambia el comportamiento: la función original devuelve '0' o' -1', pero bool es '0' y' + 1'. –

0

con C++ 11 se puede llegar muy cerca:

int foo(int a); // Forward declaration. 

int baz() { 
    int result = []{ 
     int a = dosomestuff(); 
     return foo(a); 
    }() ? 0 : -1; 
    return result; 
} 
Cuestiones relacionadas