2009-10-28 18 views
13

Si hago:¿En qué versiones de C hay un bloque entre paréntesis utilizado para devolver un valor válido?

int j = ({int x = 7; x+3;}); 

En i686-manzana-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. construir 5646) gcc compila bien. El bloque en la pregunta ({int x = 7; x+3;}) devuelve el valor de la última instrucción como el valor del bloque. Si elimina los paréntesis, no compila. ¿Puedo esperar que esto funcione en la mayoría de los compiladores de C?

Además, ¿cómo se llama esta construcción? He tenido muchos problemas para buscarlo porque los motores de búsqueda no indexan () o {} y C es un término de búsqueda terrible. Tampoco he podido encontrar nada al respecto en ninguno de mis libros, probablemente porque no sé qué buscar.

+3

No espere que funcione, y no espere que las personas para poder leer tu código – Puppe

Respuesta

7

Si elimina los paréntesis, no se compila.

Sin los paréntesis, el compilador tratará esto como un bloque de inicialización agregado y fallará cuando vea la palabra clave int. No puede tener palabras clave en los bloques de inicialización.

6.7.8 Inicialización

El inicializador para un escalar será una sola expresión, opcionalmente entre llaves. El valor inicial del objeto es el de la expresión (después de la conversión); se aplican las mismas restricciones y conversiones del tipo que para la asignación simple, tomando el tipo de escalar como la versión no calificada de su tipo declarado.

6.2.5 Tipos

tipos aritméticos y los tipos de puntero se denominan colectivamente tipos escalares. Los tipos de estructura Array y se denominan colectivamente tipos agregados.


puedo esperar que esto funcione en la mayoría de los compiladores de C?

No. Parece una extensión de GNU no estándar.

Además, ¿cómo se llama esta construcción?

Me pregunto si hay alguno. En realidad, esto es similar a lo que suelen hacer las macros.

6

Puede esperar que funcione en la mayoría de las versiones de GCC.

Puede esperar que funcione casi en ninguna otra parte: es una extensión de GCC.

La sección del manual GCC que describe la característica se titula 'instrucciones y declaraciones en expresiones':

Una declaración compuesto entre paréntesis pueden aparecer como una expresión en GNU C.

Más adelante se dice:

Cualquier temporales creados dentro de una instrucción dentro de una expresión declaración serán destruidos en t el final de la declaración Esto hace que las expresiones de las sentencias dentro de las macros sean ligeramente diferentes a las llamadas a funciones .

Por lo tanto, 'statement expression' parece ser el nombre utilizado en la documentación.

+0

clang parece apoyar esto también. – logicor

+0

Clang admite la mayoría de las cosas que GCC admite para la compatibilidad con GCC. Eso no hace que sea una buena idea, necesariamente, usarlo. Tendrás que elegir si es sensible o no. –

+0

Solo estaba diciendo hechos. Clang no es "casi en ninguna parte" en mi humilde opinión. No hay comentarios subjetivos sobre si es una buena idea usarlo. – logicor

25

Es un GCC extension:

Una sentencia compuesta entre paréntesis puede aparecer como una expresión en GNU C. Esto permite el uso de bucles, interruptores y las variables locales dentro de una expresión.

Recordar que una instrucción compuesta es una secuencia de sentencias rodeada de llaves; en este constructo, los paréntesis rodean las llaves. Por ejemplo:

({ int y = foo(); int z; 
    if (y > 0) z = y; 
    else z = - y; 
    z; }) 

es una expresión válida (aunque ligeramente más compleja de lo necesario) para el valor absoluto de foo().

Lo último en la instrucció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. (Si usa algún otro tipo de instrucción al final de las llaves, la construcción tiene el tipo void y, por lo tanto, no tiene valor). ...

Cuestiones relacionadas