¿Cuál es esta sintaxis de C ++ que coloca un bloque rodeado de llaves donde se espera una expresión?

78

Me encontré con este extraño programa de C ++.

#include <iostream>
using namespace std;
int main()
{
  int a = ({int x; cin >> x; x;});
  cout << a;
}

¿Puede alguien explicar qué está pasando? ¿Cómo se llama esta construcción?

Koshimitsu
fuente
51
se llama "ofuscar el código"
BЈовић
2
@VJo: Quiero decir, ¿cómo se llama esta construcción "({})"? ¿Es similar a las funciones anónimas?
Koshimitsu
1
+1 Vaya, nunca había visto esto antes. Lástima que de GNU C / C ++ específica ...
sehe
1
+1, se parece un poco a la función lambda :)
iammilind
18
¿Soy solo yo, o hay más extensiones extrañas no estándar en gcc que en cualquier otro compilador?
David Heffernan

Respuestas:

68

Asigna un valor de entrada del usuario ay lo imprime. se hace usando a Statement Expression.

Las expresiones de declaración son extensiones del compilador gnu gcc que no son compatibles con los estándares C / C ++. Por lo tanto, cualquier código que utilice expresiones de declaración no cumple con los estándares ni es portátil.

IBM IBM XL C / C ++ v7.0 también admite expresiones de declaración y su documentación las explica adecuadamente:

Expresiones de declaración:

Una declaración compuesta es una secuencia de declaraciones entre llaves. En GNU C, una declaración compuesta entre paréntesis puede aparecer como una expresión en lo que se llama a Statement expression.

         .--------------.
         V              |
>>-(--{----statement--;-+--}--)--------------------------------><

El valor de una expresión de declaración es el valor de la última expresión simple que aparece en la construcción completa. Si la última declaración no es una expresión, entonces la construcción es de tipo void y no tiene valor.

Siempre compilar el código seleccionando un sandard en GCC, utilice una de las opciones -ansi, -std=c90o -std=iso9899:1990, -std=c++03, -std=c++0x; para obtener todos los diagnósticos requeridos por el estándar, también debe especificar -pedantic(o -pedantic-errorssi desea que sean errores en lugar de advertencias)

Alok Save
fuente
56

Es una extensión de GCC. Compilar el código con el -pedanticindicador si desea deshacerse de cosas como esta (y que realmente no quiere).


fuente
10
Sospecho que obtuvo tantos votos porque mucha gente se sintió aliviada después de enterarse de que algo de lo que no habían oído hablar o usado no es estándar de todos modos.
Blagovest Buyukliev
18

Crea un alcance en línea, declara xdentro de él, lo lee de la entrada estándar y finalmente se evalúa la declaración completa a x, que se asigna a a.

El operador de coma funciona de manera similar, aunque no requiere un alcance separado. Por ejemplo:

int x;
int a = (cin >> x, x);

haría lo mismo. Todas las sentencias conectadas con comas se ejecutarán secuencialmente y el resultado de toda la expresión se establecerá en el valor del operando situado más a la derecha.

Blagovest Buyukliev
fuente
¿Existe algún nombre específico para "({})"?
Koshimitsu
@Koshimitsu: No lo hay, porque es una combinación de operadores (si desea llamarlos así). Las llaves {} definen el inicio ({) y el final (}) de un ámbito en este caso. Los corchetes regulares están ahí para encapsular la definición del alcance y el valor de retorno. No estoy completamente seguro de si estos corchetes regulares se pueden omitir en este caso, sin embargo, espero que puedan.
Rycul
1
@Koshimitsu: No estoy muy familiarizado con C ++, pero en C es perfectamente legal y lo he usado muchas veces.
Blagovest Buyukliev
1
@Neil: bueno, tal vez sea porque gcc es el único compilador de C que uso, por lo que me engañé.
Blagovest Buyukliev
13

No creo que esto sea C ++ estándar. Probablemente sea una extensión específica del compilador que permite que un ámbito interno evalúe un valor.

Oliver Charlesworth
fuente
1
@Doc: Tonterías. Eso no es C estándar, para empezar. Es posible que se haya agregado a C ++ 0x, no lo sé.
Oliver Charlesworth
13
@Doc estás equivocado. No es C ++ estándar ni C. Es una extensión GCC llamada "expresión de declaración".
Johannes Schaub - litb
No creo que lo sea. Visual Studio ciertamente no lo aceptará.
Puppy
3
@mathepic: tampoco GCC aparentemente (sin las opciones correctas), de ahí la pregunta y la confusión aquí ...
rubenvb