#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?
#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?
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 :-)
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.
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.
Una invocación más probable es 'max (* p ++, * q ++) '. –
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.
¿Puedo estar seguro de que el compilador no crea una instancia de la unión? – pezcode
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
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 ... –