tutorial preprocesadores c++ c macros preprocessor

c++ - tutorial - preprocesadores html



¿Cuál es el peor abuso de macros/pre-procesadores del mundo real con el que se haya topado? (30)

¿Mundo real? MSVC tiene macros en minmax.h, llamadas max y min , que causan un error de compilación cada vez que pretendo usar la función estándar std::numeric_limits<T>::max() .

¿Cuál es el peor abuso de macros / pre-procesadores del mundo real con el que te has encontrado alguna vez (por favor, no hay respuestas IOCCC ideadas * jaja *)?

Agregue un pequeño fragmento o historia si es realmente entretenido. El objetivo es enseñar algo en lugar de decirle siempre a las personas que "nunca usen macros".

ps: He usado macros antes ... pero usualmente me deshago de ellos cuando tengo una solución "real" (incluso si la solución real está en línea por lo que se vuelve similar a una macro).

Bonificación: dé un ejemplo de que la macro realmente era mejor que una solución no macro.

Pregunta relacionada: ¿ Cuándo son beneficiosas las macros C ++?


Desde la memoria, se veía algo como esto:

#define RETURN(result) return (result);} int myfunction1(args) { int x = 0; // do something RETURN(x) int myfunction2(args) { int y = 0; // do something RETURN(y) int myfunction3(args) { int z = 0; // do something RETURN(z)

Sí, eso es correcto, sin llaves de cierre en ninguna de las funciones. El resaltado de sintaxis era un desastre, por lo que usó vi para editar (no vim, ¡tiene coloreado de sintaxis!)

Era un programador ruso que casi siempre había trabajado en lenguaje ensamblador. Era fanático de salvar tantos bytes como fuera posible porque anteriormente había trabajado en sistemas con memoria muy limitada. "Era para satélite. Solo muy pocos bytes, así que usamos cada byte para muchas cosas". (tropezando un poco, reutilizando bytes de instrucciones de la máquina para sus valores numéricos) Cuando traté de averiguar qué tipo de satélites, solo pude obtener "Orbiting satellite. Para hacer orbitar".

Tenía otros dos caprichos: un espejo convexo montado sobre su monitor "Para saber quién está mirando", y una ocasional salida repentina de su silla para hacer unas diez flexiones rápidas. Explicó este último como "El compilador encontró un error en el código. Esto es un castigo".


Directamente desde Qt:

#define slots /* */ #define signals /* */

Muy bueno para interactuar con otras librerías como boost :: signals ... Solo un ejemplo, hay muchas otras en Qt que crean código de aspecto divertido como:

class X : public QObject { Q_OBJECT private slots: //... public signals: //... };

Y eso es C ++ ... pero de repente:

boost::signals::trackable

Ya no es válido C ++.


Hice lo siguiente, y creo que aprendí algo de eso.

En 1992 o algo así, escribí un pequeño intérprete de Lisp. No se implementó en C normal, sino en un lenguaje interpretado como C. Sin embargo, este lenguaje tipo C usó el preprocesador estándar C.

El intérprete de Lisp, por supuesto, contenía las funciones auto , que se usa en Lisp para devolver el primer elemento en una lista, y cdr , que devuelve el resto de la lista. Fueron implementados así:

LISPID car(LISPID id) { CHECK_CONS("car", 1, id); return cons_cars[id - CONS_OFFSET]; } /* car */ LISPID cdr(LISPID id) { CHECK_CONS("cdr", 1, id); return cons_cdrs[id - CONS_OFFSET]; } /* cdr */

(Los datos se almacenaron en matrices, ya que no había estructuras. CONS_OFFSET es la constante 1000).

car y cdr se usan con frecuencia en Lisp, y son cortos, y como las llamadas a funciones no eran muy rápidas en el lenguaje de implementación, optimicé mi código implementando esas dos funciones de Lisp como macros:

#define car(id) (CHECK_CONS("car", 1, (id)), cons_cars[(id) - CONS_OFFSET]) #define cdr(id) (CHECK_CONS("car", 1, (id)), cons_cdrs[(id) - CONS_OFFSET])

CHECK_CONS comprueba que su argumento en realidad es una lista, y dado que ese también se usa con frecuencia en el intérprete, y es corto, también lo escribí como una macro:

#define CHECK_CONS(fun, pos, arg) / (!IS_CONS(arg) ? / LISP_ERROR("Arg " + pos + " to " + fun + / " must be a list: " + lispid2string(arg)) : 0)

IS_CONS y LISP_ERROR también se usaron con frecuencia, por lo que también los convertí en macros:

#define IS_CONS(id) / ( intp(id) && (id) >= CONS_OFFSET / && ((id) - CONS_OFFSET) < sizeof(cons_cars)) #define LISP_ERROR(str) (throw((str) + "/n"))

¿Parece razonable?

Pero entonces, ¿por qué el sistema completo se coló en esta línea?

id2 = car(car(car(car((id1))));

Trabajé mucho tiempo para encontrar el problema, hasta que finalmente verifiqué a qué línea corta se había expandido el preprocesador. Se expandió a una línea de 31370 caracteres, que he dividido aquí en líneas (502 de ellos) para mayor claridad:

id2 = ((!(intp( (((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])) - 1000]))) >= 1000 && (( (((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000])) - 1000])) - 1000])))) + "/n")) : 0), cons_cars[(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " + lispid2string( (id1))) + "/n")) : 0), cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars))


Lo horrible

#define begin { #define end } /* and so on */

En serio, si quieres codificar en Pascal, compra un compilador Pascal, no destruyas el hermoso lenguaje C.


Me gustaría enviar para el concurso una joya llamada chaos-pp , que implementa un lenguaje funcional por medio de las macros del preprocesador.

Uno de los ejemplos es calcular el número 500 de fibonacci por completo por el preprocesador:

El código original antes del preprocesador se ve así:

int main(void) { printf ("The 500th Fibonacci number is " ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0))))) "./n"); return 0; }

preprocesando el archivo obtenemos el siguiente resultado (después de una espera bastante larga):

$ cpp -I../inc fibonacci.c 2>/dev/null | tail return fib_iter(n, 0, 1); } # 63 "fibonacci.c" int main(void) { printf ("The 500th Fibonacci number is " "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125" "./n"); return 0; }


Mi peor:

#define InterlockedIncrement(x) (x)++ #define InterlockedDecrement(x) (x)--

Pasé dos días de mi vida rastreando un problema de recuento de referencias COM de subprocesos múltiples porque un idiota puso esto en un archivo de encabezado. No mencionaré la empresa para la que trabajé en ese momento.

La moraleja de esta historia? Si no entiende algo, lea la documentación y aprenda sobre ella. No lo hagas desaparecer.


Raymond Chen tiene una muy buena queja contra el uso de macros de control de flujo . Su mejor ejemplo es directamente del código fuente del shell Bourne original:

ADDRESS alloc(nbytes) POS nbytes; { REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD); LOOP INT c=0; REG BLKPTR p = blokp; REG BLKPTR q; REP IF !busy(p) THEN WHILE !busy(q = p->word) DO p->word = q->word OD IF ADR(q)-ADR(p) >= rbytes THEN blokp = BLK(ADR(p)+rbytes); IF q > blokp THEN blokp->word = p->word; FI p->word=BLK(Rcheat(blokp)|BUSY); return(ADR(p+1)); FI FI q = p; p = BLK(Rcheat(p->word)&~BUSY); PER p>q ORF (c++)==0 DONE addblok(rbytes); POOL }


Un ''arquitecto'', un tipo muy humilde, ya sabes el tipo, tenía lo siguiente:

#define retrun return

porque le gustaba escribir rápido. Al cirujano cerebral le gustaba gritarle a las personas que eran más inteligentes que él (que era casi todo el mundo), y amenazaba con usar su cinturón negro sobre ellas.


Un compañero de trabajo y yo encontramos estas dos gemas en algunos de nuestros códigos para la transmisión de objetos. Estas macros se instanciaron en CADA archivo de clase SINGLE que hizo la transmisión. No solo se esparció este horrible código por todo nuestro código base, cuando nos acercamos al autor original al respecto, escribió un artículo de 7 páginas sobre nuestro wiki interno defendiéndolo como la única forma posible de lograr lo que intentaba hacer aquí.

Huelga decir que desde entonces se ha refactorizado y ya no se usa en nuestra base de códigos.

No te desanimes con las palabras clave resaltadas. Esto es TODO una macro

#define DECLARE_MODIFICATION_REQUEST_PACKET( T ) / namespace NameSpace / { / / class T##ElementModificationRequestPacket; / } / / DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) / DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> ) / DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> ) / / namespace NameSpace { / class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>/ { / public: / T##ModificationRequestPacket( NetBase * pParent ) / : ElementModificationRequestPacket<T>( pParent ), m_Gen() {} / / T##ModificationRequestPacket( NetBase * pParent, / Action eAction, / const T & rT ) / : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {} / / T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs ) / : ElementModificationRequestPacket<T>( rhs ), m_Gen() {} / / virtual ~T##ModificationRequestPacket( void ) {} / / virtual Uint32 GetPacketTypeID( void ) const / { / return Net::T##_Modification_REQUEST_PACKET; / } / / virtual OtherNameSpace::ClassID GetClassID ( void ) const / { / return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING, / Net::T##_Modification_REQUEST_PACKET ); / } / / virtual T##ModificationRequestPacket * Create( void ) const / { return new T##ModificationRequestPacket( m_pParent ); } / / T##ModificationRequestPacket() {} / / protected: / OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen; / / friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >; / OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> > m_Stream; / / }; / } / DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> ) / DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> ) / typedef ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket> T##ModifiedBroadcaster; #define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T ) / DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket<T> ) / DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> ) / DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> ) / INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) / INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )

Actualización (17 de diciembre de 2009):

Más buenas noticias sobre este horrible autor macro. A partir de agosto, el empleado responsable de esta monstruosidad fue despedido.


Una mezcla entre la sintaxis de Pascal y las palabras clave francesas:

#define debut { #define fin } #define si if( #define alors ){ #define sinon }else{ #define finsi }


Windows.h tiene muchas funciones que abusaron de las macros.

Mr Valdez está molesto por la macro GetObject que se encuentra en Windows.h

La macro GetObject cambia la función GetObject () en GetObjectA () o GetObjectW () (dependiendo de si la compilación está compilada en unicode y no unicode, respectivamente)

El Sr. Valdez odia tener que hacer antes de la línea de función GetObject

#undef GetObject Object *GetObject()

La alternativa es cambiar el nombre de la función a otra cosa como GetGameObject ()

jdkoftinoff en los comentarios lo tienen claro: el problema es que todas las funciones de la API de Windows son macros.

Adam Rosenfield mencionó que los problemas se pueden solucionar definiendo NOGDI, WIN32_LEAN_AND_MEAN, NOMINMAX, etc. antes de incluir windows.h para eliminar los problemas.


ASA - http://www.ingber.com/#ASA

You really have to download it to appreciate it. The entire work flow is determined by macros. It is completely unreadable. As an example -

if (asa_open == FALSE) { asa_open = TRUE; ++number_asa_open; #if ASA_PRINT if (number_asa_open == 1) { /* open the output file */ #if USER_ASA_OUT if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { #if ASA_SAVE ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a"); #else ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w"); #endif } #else /* USER_ASA_OUT */ if (!strcmp (ASA_OUT, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { #if ASA_SAVE ptr_asa_out = fopen (ASA_OUT, "a"); #else ptr_asa_out = fopen (ASA_OUT, "w"); #endif } #endif /* USER_ASA_OUT */ } else { #if USER_ASA_OUT if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a"); } #else if (!strcmp (ASA_OUT, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { ptr_asa_out = fopen (ASA_OUT, "a"); } #endif fprintf (ptr_asa_out, "/n/n/t/t number_asa_open = %d/n", number_asa_open); } #endif /* ASA_PRINT */ } else { ++recursive_asa_open; #if ASA_PRINT if (recursive_asa_open == 1) { /* open the output file */ #if ASA_SAVE #if USER_ASA_OUT if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a"); } #else if (!strcmp (ASA_OUT, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else { ptr_asa_out = fopen (ASA_OUT, "a"); } #endif #else /* ASA_SAVE */ #if USER_ASA_OUT if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) { #if INCL_STDOUT ptr_asa_out = stdout; #endif /* INCL_STDOUT */ } else {

etc., etc.

And that is just setting up the options. the entire program is like that.


By a classmate who failed to understand the rules about magic numbers:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1


I maintain code that has gotos in macros. So a function will have a label at the end but no visible goto in the function code. To make matters worse the macro is at the end of other statements usually off the screen unless you scroll horizontally.

#define CHECK_ERROR if (!SomeCondition) goto Cleanup void SomeFunction() { SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR //SomeOtherCode Cleanup: //Cleanup code }


I once had to port a C application from unix to windows, the specific nature of which shall remain unnamed to protect the guilty. The guy who wrote it was a professor unaccustomed to writing production code, and had clearly come to C from some other language. It also happens that English wasn''t his first language, though the country he came from the majority of people speak it quite well.

His application made heavy use of the preprocessor to twist the C language into a format he could better understand. But the macros he used the most were defined in a header file named ''Thing.h'' (seriously), which included the following:

#define I Any void_me #define thou Any void_thee #define iam(klas) klas me = (klas) void_me #define thouart(klas) klas thee = (klas) void_thee #define my me -> #define thy thee -> #define his him -> #define our my methods -> #define your thy methods ->

...which he then used to write monstrosities like the following:

void Thing_setName (I, const char *name) { iam (Thing); if (name != my name) { Melder_free (my name); my name = Melder_wcsdup (name); } our nameChanged (me); } void Thing_overrideClass (I, void *klas) { iam (Thing); my methods = (Thing_Table)klas; if (! ((Thing_Table) klas) -> destroy) ((Thing_Table) klas) -> _initialize (klas); }

The entire project (~60,000 LOC) was written in a similar style -- marco hell, weird names, Olde-English jargon, etc. Fortunately we were able to throw the code out since I found an OSS library which performed the same algorithm dozens of times faster.

(I''ve copied and edited this answer which I originally made on this question ).


I was bored one day and was playing around with blocks in Objective-C...

#define Lambda(var, body) [^ id(id (var)) { return (body);} copy] #define Call(f, arg) ((id(^)(id))(f))(arg) #define Int(num) [NSNumber numberWithInteger:(num)] #define Mult(a, b) Int([(a) integerValue] * [(b) integerValue]) #define Add(a, b) Int([(a) integerValue] + [(b) integerValue]) #define Sub1(n) Int([(n) integerValue] - 1) #define Add1(n) Int([(n) integerValue] + 1) #define If(cond, thenblock, elseblock) ([(cond) integerValue] ? (thenblock) : (elseblock)) #define Cons(car, cdr_) [[ConsType alloc] initWithCar:(car) cdr:(cdr_)] #define Car(list) [(list) car] #define Cdr(list) [(list) cdr] #define Define(var, value) id var = (value) #define Nullq(value) Int(value == nil)

allowing "interesting" things like:

Define(Y, Lambda(f, Call(Lambda(x, Call(x, x)), Lambda(x, Call(f, Lambda(y, Call(Call(x, x), y))))))); Define(AlmostTotal, Lambda(f, Lambda(list, If(Nullq(list), Int(0), Add(Car(list), Call(f, Cdr(list))))))); Define(Total, Call(Y, AlmostTotal)); Print(Call(Total, Cons(Int(4), Cons(Int(5), Cons(Int(8), nil)))));

(some function and class definitions not shown for sake of brevity)


In one year of the International Obfuscated C Coding Contest, there was an entry where the entire program was:

P

With the proviso that you could define P in the makefile to be whatever program you wanted.

As I recall, it won in one of the categories, and the next year a rule had popped up disallowing that style of entry.

(Edit: six months later or something... I''m sure the "No IOCCC" thing wasn''t in the main question when I wrote this...)


One fairly bad example:

#ifdef __cplusplus #define class _vclass #endif

This allows a C structure that contains a member variable called class to be handled by a C++ compiler. There are two headers with this construct in it; one of them also contains ''#undef class'' at the end and the other doesn''t.


The obligatory

#define FOR for

y

#define ONE 1 #define TWO 2 ...

Who knew?


The use of the LINE preprocessor to generate unique ID for messages passed over the network:

NetworkMessages.h #define MSG_LOGIN __LINE__ #define MSG_LOGOUT __LINE__ #define MSG_CHAT __LINE__

This is an example where the macro really was better than a non-macro solution:

In a non-macro solution classes, functions and variables have to be built to keep track of what ID the message is. The developer may or may not make the message ID tracking complicated whereas this is easier to read and debug.

In addition, its easier to add new messages just by adding the message into the source.

The disadvantage of this situation is that the file has to be included in all code that uses messages. Compile time would increase whenever a message is edited.


The worst I''ve ever encountered was in a product containing a suite of executables where the designated technical leader hadn''t figured out libraries.

Instead, he had sets of files that were shared in several Visual Source Safe folders. He then realised they needed to behave slightly differently for each application.

There''s a number of refactoring steps you could apply here.

Instead, he used #ifdefs

void DisplayLoadError() { #if defined __TIMETABLE_EDITOR MessageBox("Timetable Editor failed to load the correct timetable", MB_ERROR); #else if defined __SCHEDULESET_EDITOR MessageBox("Schedule Set Editor faied to load the correct Schedule Set", MB_ERROR); #else if defined __ROSTER_EDITOR MessageBox("Roster Editor failed to load the correct Roster", MB_ERROR); #endif }


The worst one I saw was the non-use :-)

Someone wrote a strcpy (I think that was it... over 10 years ago now) function inside of a method (because they didn''t want the overhead of calling strcpy... sigh).

They clued in that it wouldn''t work for Japanese characters so they added an "if" at the start to do ASCII or Unicode. At that point the code was about a screen long... likely killing cache coherency and erasing his supposed savings for the inlining of the code.

The code was identical save for the types (so should have used a macro).

Of course the strcpy that they wrote was much much much slower than the hand tuned assembler one that was in the standard library...

Of course if they had just done it all as a macro it could have been replaced with a call to strcpy...

Of course I quit the company (not directly because of that...)


#define TRUE 0 // dumbass

The person who did this explained himself some years later - most (if not all) C library functions return 0 as an indication that everything went well. So, he wanted to be able to write code like:

if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) { ; // rape that packet }

Needless to say, nobody in our team (tester or developer) ever dared to glance at his code again.


#define ever (;;) for ever { ... }


#define if while

Fue una broma jugada sobre alguien, no fue divertida para los afectados


#define private public


#define return if (std::random(1000) < 2) throw std::exception(); else return

esto es tan malo. Es aleatorio, lo que significa que dispara en diferentes lugares todo el tiempo, cambia la declaración de retorno, que generalmente tiene algún código que podría fallar por sí solo, cambia la palabra clave de aspecto inocente que nunca se volverá sospechoso y utiliza excepción del espacio estándar, por lo que no intentará buscar en sus fuentes para encontrar su fuente. Sólo brillante.


#include <iostream> #define System S s;s #define public #define static #define void int #define main(x) main() struct F{void println(char* s){std::cout << s << std::endl;}}; struct S{F out;}; public static void main(String[] args) { System.out.println("Hello World!"); }

Desafío: ¿Alguien puede hacerlo con menos definiciones y estructuras? ;-)


#include <iostream> #define public_static_void_main(x) int main() #define System_out_println(x) std::cout << x << std::endl public_static_void_main(String[] args) { System_out_println("Hello World!"); }