Aspies For Freedom

Full Version: The beauty of macros (C/C++ ones)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
One of my favorite features of C and C++ is the preprocessor's macro-features. There are few things as beautiful as a well-defined, efficient macro. As far as language syntax go, macros are one of the main features that IMO make C++ vastly superior to Java. (another one would be pointers)

There are so many wonderful things you can do using macros that are not otherwise possible, and they are far more efficient than inline functions using reference parameters. (atleast for me, using GCC)

I hereby declare C-macros holy! May their divine beauty always be present within your C and C++ source.




By the way, someone should send the following to Bjarne Stroustrup:

Code:
#if IN_SOVIET_RUSSIA
#  define Bjarne "evil"
#endif

defines are very sexy, i'm unsure about macros

personally, i find that macros make code look messy and i don't like them

and C++ shall be woodled!
There is this thing called the "International Obfuscated C Code Contest."  The point of the contest (which was inspired by the Unix kernel source) is to write the most terrible, but functional, code possible.  One of the winners from years ago was just piles and piles of preprocessor code.

Using macros, the guy who wrote it built flip-flops, from them he built gates, from them an ALU, and so on, and then he had a bunch of preprocessor code which would use them to calculate Pi.  The code was an absolute horrid and tangled mess of preprocessor directives that took DAYS to go through the preprocessor, and what came out?  The following:

#include <stdio.h>
int main()
{
      printf ("3.1415926535897932384626433832795");
      return 0;
}
Though I have not seen that one, I know of the contest and have seen other entries. Not quite what I want to achieve.

This part of a header used by processing code of my plugins making use of envelope detection is a pretty good example of what I concider beautiful macros: (making use of GNU C extensions, a near-necessity. also note: the comments should look better, but the space before the '*'s on the lines below the first seem to be ommited)

Code:
/*
* Avg (basic averager/envelope follower)
*/

/* averager data struct */
typedef struct
{
  double coeff;
  /* parameters */
  float ms;
} Avg;

/* coeffs-only Avg struct */
typedef struct
{
  double coeff;
} Avg_c;

/* Avg_RUN_*:
*  Macros for updating the state of the filter. Apart from the st parameter
*  (which must also be assignable) they are "safe".
*/
/* simple exponential averager
*/
#define Avg_RUN_EXP(a, in, st) ({\
  typeof(in) _in = (in); \
  Avg_c *const _a = (Avg_c*) &(a); \
  st = _in + _a->coeff * (st-_in); \
})
/* attack/release combination
*/
#define Avg_RUN_ARENV(at, re, in, st) ({\
  typeof(in) _in = (in); \
  Avg_c *const _a = (Avg_c*) (_in > st ? &(at) : &(re)); \
  st = _in + _a->coeff * (st-_in); \
})
/* zero-attack version
*/
#define Avg_RUN_ZAENV(re, in, st) ({\
  typeof(in) _in = (in); \
  Avg_c *const _a = (Avg_c*) &(re); \
  st = (_in > st) ? _in : (_in + _a->coeff * (st-_in)); \
})
/* zero-release version
*/
#define Avg_RUN_ZRENV(at, in, st) ({\
  typeof(in) _in = (in); \
  Avg_c *const _a = (Avg_c*) &(at); \
  st = (_in > st) ? (_in + _a->coeff * (st-_in)) : _in; \
})

/* Avg_UPDATE:
*  Updates data according to sample rate. (is "safe")
*/
#define Avg_UPDATE(a, sr) ({\
  Avg *const _a = &(a); \
  _a->coeff = RC_TIME_COEFF(_a->ms, sr); \
})

I'm curious as to what this buys you over inline functions (assuming you are using C++ as opposed to C.)  Is it purely a performance gain?
C macros are junkyard scrap compared to LISP macros.

For a quick explanation of how, go to http://www.defmacro.org/ramblings/lisp.html and scroll down/search for "C Macros Reloaded." The article as a whole is meant to explain LISP concepts by making comparisons to hypothetical, well-explained modifcations to applications that most programmers are more familiar with.

Quote:
As far as language syntax go, macros are one of the main features that IMO make C++ vastly superior to Java. (another one would be pointers)


Macros? Java doesn't have macros? I can fix that..easily.

All I need to do is change my IDE's compile tool to something like "ruby MyJavaMacroMaker.rb [FileName]". This will then execute a (currently-nonexistent, but for me easy to write) Ruby program, sending it the name of the file to be compiled as a command line argument. Said program would then read in the file, do some quick Regular-expression-powered string manipulations to do the equivalent of a preprocessor-macro, make a copy in a subdirectory, send the compile command to the operating system, and echo the results back. Might increase the compile time a bit, but still - that basically gives macros in Java (or any other language).

As for pointers? Java does have pointers. It's just that you can't choose if something is a pointer or not; all primitive values (e.g.: int, char, float) are not-pointers; all Objects (e.g.: String, Integer, Character, LinkedList, TextBox - everything except primitives) are pointers.

But, yes, it does not have C-style pointers. That is a mixed blessing; on one hand it eliminates a source of errors and gets away from the low level; on another hand, it makes it harder to return many values.

However, Java also has many things that C++ doesn't.

AsAdam2Eve Wrote:
I'm curious as to what this buys you over inline functions (assuming you are using C++ as opposed to C.)  Is it purely a performance gain?

That was the original reason for switching from classes with inline functions to structs and macros. Then I soon grew fond of the new coding style and the conciseness of the new parts of the library. Eventually, I converted the processing code of the DSP plugins in question to pure (GNU-extended) C, (though I have recently began using inline assembly optimizations. only to a very small extent so far, but already with very impressive results. mayhaps those macros will one day contain such, instead...) and have since managed to squeeze out more than would otherwise have been possible.

Seeing as it is my freetime project, where I am free to set the priorities as I want, I have decided to concentrate more or less obsessively on performance. It is the most interesting programming I have done so far, and I have learned a lot about efficient coding on the lower levels.

Reference URL's