2011-03-16 20 views
8
#define max(a,b) \ 
    ({ typeof (a) _a = (a); \ 
     typeof (b) _b = (b); \ 
    _a > _b ? _a : _b; }) 

¿Por qué no simplemente (a>b ? a : b)?¿Por qué la macro 'max' se define así en C?

+3

Tenga en cuenta que typeof es una palabra clave no estándar que puede encontrar en las extensiones de GCC y similares. En un estricto compilador C/C++, typeof() no se compilará. – Lundin

+2

Porque la gente de GNU preferiría tener un código feo e ilegible lleno de hacks específicos de GNU que simplemente documentar que no se pueden pasar expresiones con efectos secundarios a una macro ... –

Respuesta

19

porque otherwhise max(f(1), f(2)) llamarían una de las dos funciones en dos ocasiones:

f(1) > f(2) ? f(1) : f(2) 

no por los dos valores en _a y _b que tiene

({ 
    sometype _a = (a); 
    sometype _b = (b); 

    _a > _b ? _a : _b; 
}) 

(y claramente como otra tienen "caching" señaló, existe el mismo problema con autoincrement/autodecrement)

No creo que esto es compatible con Visual S tudio de esta manera. Esta es una declaración compuesta. Lea aquí does msvc have analog of gcc's ({ })

voy a añadir que la definición de instrucción compuesta en el manual de gcc dada aquí http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62 muestra un código muy similar a la de la pregunta para max :-)

8

Se está haciendo todo el principal problema de cosas como

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

cuando se llama con:

int x = max (a++, b--); 

Ya que es la sustitución de texto simple, que se traduce en:

int x = ((a++) > (b--) ? a++ : b--); 

que es no lo desea.

Mediante el uso de:

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

que utiliza variables temporales que efectivamente le da:

int x = ({ int _a = a++; int _b = b--; _a > _b ? _a : _b; }) 

que corre los efectos secundarios sólo se vez.

Pero, para ser honesta, debe zanja esa macro en conjunto y utilizar una función inline, o incluso una función no en línea, ya que, la mayoría de las veces, el compilador puede hacer un buen trabajo de optimización aun sin esa sugerencia.

1

Si se llama a la macro con expresión, esto podría provocar un comportamiento inesperado. Supongamos la siguiente:

int c = max(i++, j++);

En este caso, el aumento máximo es dos veces con la versión más simple.

+0

Una invocación más probable es 'max (* p ++, * q ++) '. –

3

Otra manera de determinar max (al menos para los números positivos)

#define MAX(a,b) sizeof(union x { char ca[a]; char cb[b];}) 

como A y B se accede sólo una vez, MAX (a ++, b ++) da el resultado correcto.

+0

¿Puedo estar seguro de que el compilador no crea una instancia de la unión? – pezcode

Cuestiones relacionadas