2011-10-19 19 views
11

poco encontré esta macro GCC:¿Cómo `({...})` devuelve un valor?

#define max(a,b) \ 
    ({ typeof (a) _a = (a); \ 
     typeof (b) _b = (b); \ 
    _a > _b ? _a : _b; }) 

no me di cuenta antes de ver este código, que un bloque de código puede {...} valor de alguna manera volver en C.
1) ¿Me podría dar una ¿Insinúa cómo funciona esto?

Aunque, por lo general era capaz de conseguir el mismo resultado mediante el abuso del operador coma:

#define max(a,b) \ 
    (typeof (a) _a = (a), \ 
    typeof (b) _b = (b), \ 
    (_a > _b ? _a : _b)) 

o si sólo era para efecto secundario, lo usaría do { ... } while(0)

2) ¿Qué es la forma preferida de hacer esto?

+1

que podría convertirse en una pregunta protegida! muchos programadores C (y C++, creo) no saben que '({...})' es una extensión GCC y no parte del lenguaje C. EN MI HUMILDE OPINIÓN. – Jack

Respuesta

9

La construcción ({ ... }) es una extensión gcc.

Así es el operador typeof.

Un MAX macro (nótese el uso convencional de todo en mayúsculas) es bastante fácil de escribir:

#define MAX(a, b) ((a) > (b) ? (a) : (b)) 

No evaluar uno de sus argumentos más de una vez, así que no debería invocar como, por ejemplo, MAX(x++, y--). El uso de mayúsculas sirve para recordarle al usuario que se trata de una macro, no una función, y de tener cuidado con argumentos con efectos secundarios.

O puede escribir una función (tal vez una en línea) para cada tipo.

+2

+1 Wow: - |, realmente no sabía nada de '({...})'. Deben ponerlo totalmente en el lenguaje. – cnicutar

+2

Gracias por el enlace ['({...})'] (http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Statement-Exprs.html#Statement-Exprs). Siempre es difícil buscar en Google con solo puntuación. – Halst

10

Es una extensión de GCC. El operador coma no funciona:

// C89, doesn't work... 
#define max(a,b) \ 
    (typeof (a) _a = (a), \ 
    typeof (b) _b = (b), \ 
    (_a > _b ? _a : _b)) 

operador de la coma sólo funciona con expresiones y typeof(a) _a = (a); es una declaración, no una expresión. No es posible escribir una macro equivalente sin extensiones GCC o C11, que tiene _Generic. Tenga en cuenta que typeof es también una extensión de GCC, por lo que no gana ninguna portabilidad eliminando ({...}) a menos que elimine typeof también.

Aquí hay una versión C11, fíjate cuan prolija es en comparación (¡y solo maneja dos tipos!). C11 no es ni siquiera el apoyo, sin embargo, la buena suerte tratando de encontrar un compilador para probar esto:

// C11 
static inline int maxi(int x, int y) { return x > y ? x : y; } 
static inline long maxl(long x, long y) { return x > y ? x : y; } 
#define max(x, y) _Generic((x), \ 
    long: maxl(x,y), \ 
    int:_Generic((y), \ 
     int: maxi(x,y), \ 
     long: maxl(x,y))) 

En portátil C99, puede escribir una función de macro o en línea que logra el mismo efecto, excepto que sólo produce trabajar para un tipo por macro.

// C99 
static inline int maxi(int x, int y) { return x > y ? x : y; } 

En C89/C90, no puedo pensar en ninguna manera de escribir la macro de una manera tal que no evaluará x o y dos veces.

+7

Por favor, no escriba una respuesta que no diga nada. Solo espere su tiempo y escriba una buena respuesta. Obtendrá muchos votos ascendentes si es bueno. No es necesario tratar de reclamar la pregunta como propia. –

+0

Lo siento, estoy en una terminal desconocida y estoy tratando de guardar borradores para no perder lo que escribo. No estoy realmente tratando de "reclamar la pregunta como la mía". –

+1

Ok, +1 ahora, excelente respuesta –

Cuestiones relacionadas