Nifty macros

Let's have a thread where people can post useful macros! I'll start:

1
2
3
4
5
6
#define repeat(x) for(unsigned repeat_var=0;repeat_var<x;++repeat_var)
#define BIT(x,y) (((x)>>(sizeof(x)-(y)))&1)
#define DEBUG cout<<"DEBUG"
//OR
#define DEBUG MessageBox(0,"DEBUG","DEBUG",MB_OK)
I am possibly the king of evil, unsafe macros.
1
2
3
4
5
6
7
8
9
#define arraysize(array)	(sizeof(array) / sizeof((array)[0]))

#define check_bit(var, pos)	(!!((var) & (1 << (pos))))
#define toggle_bit(var, pos)	((var) ^= (1 << (pos)))
#define set_bit(var, pos)	((var) |= (1 << (pos)))
#define clear_bit(var, pos)	((var) &= (1 << (pos)))

#define likely(expression)	(__builtin_expect((expression), 1))
#define unlikely(expression)	(__builtin_expect((expression), 0)) 

I stole the last two from Linux. Also, they only work with gcc AFAIK.

Note: arraysize() only works if the compiler knows how many elements the array has.
Last edited on
I feel the need to play devil's advocate here. Poor use of macros are dangerous.

#define repeat(x) for(unsigned repeat_var=0;repeat_var<x;++repeat_var)

This is admittedly an interesting one... although the use of 'repeat_var' makes it a little awkward. Even if you can remember that the loop counter is named repeat_var, you still have other problems. The biggest one I can think of would be inability to nest loops.

Something like this would be better, IMO:

#define repeat(i,x) for(unsigned i=0; i< x; ++i)

That way you can nest loops and give each loop it's own counter.

But is is really worth it? for loops aren't exactly difficult/time consuming to write.

*shrug*

#define BIT(x,y) (((x)>>(sizeof(x)-(y)))&1)

I think I see what this is trying to do, but it doesn't work right. I think you have your bit numberings backwards (bit 0 is the least significant bit, not the most significant), and sizeof() returns the size in bytes, not bits.

#define DEBUG cout<<"DEBUG"

I don't see what practical use this would have. However it would conflict nicely with the DEBUG symbol that's likely already defined by the compiler.

#define arraysize(array) (sizeof(array) / sizeof((array)[0]))

The templated solution is superior:

 
template <typename T,unsigned S> inline unsigned arraysize(const T (&v)[S]){ return S; }


Misusing the macro version (by giving it a vector, pointer, or dynamically allocated array) will compile OK but give you bad results/runtime errors. However the template version will give you a compiler error if you try to misuse it.

#define check_bit(var, pos), toggle_bit, etc

These would all be better as inline functions. Also your clear_bit is missing a ~ ;P
I could also do this:
1
2
#define unless(x) if (!(x))
#define until(x) while (!(x)) 

but it would look too much like I was trying to write Perl. I already get flak for doing exit(main(len(sys.argv), sys.argv) in Python so that I can define main() as def main(argc, argv).

Disch wrote:
#define arraysize(array) (sizeof(array) / sizeof((array)[0]))

The templated solution is superior:
template <typename T,unsigned S> inline unsigned arraysize(const T (&v)[S]){ return S; }

I agree, but C doesn't have templates and most of my programming (still) is in C. I have no idea why I'm still using C instead of C++, but whatever...

Disch wrote:
These would all be better as inline functions. Also your clear_bit is missing a ~ ;P

So it is...
Last edited on
I use the DEBUG macro to see what statements are crashing my program. Just type "DEBUG" before and after a statement, and if "DEBUG" doesn't appear when you put it after, that statement is crashing it.

As for the BIT macro, whoops :P I think it should be:

#define BIT(x,y) (((x)>>(sizeof(x)>>3-(y)))&1)

For some reason, I find it more intuitive to think of x as an array of bits, and the one to the left (the most significant bit) would be at index 0. But, it does make more sense for the least significant bit to be at index 0, in which case the macro would be:

#define BIT(x,y) (((x)>>(y))&1)

Maybe I'll post a few more:

1
2
3
4
5
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
#define SIGN(x) ((x)>0?1:((x)<0?-1:0))
#define PRINT(x) {cout<<#x<<": "<<x;}

BTW, chrisname, what do those last two Linux macros do?
Last edited on
PiMaster wrote:
I use the DEBUG macro to see what statements are crashing my program. Just type "DEBUG" before and after a statement, and if "DEBUG" doesn't appear when you put it after, that statement is crashing it.

Why not just use assert()? That way you can just #define NDEBUG if you want to disable assertions.

Just one caveat for assert(), though. Don't do this: assert(do_something() == SUCCESS); because when you disable assertions, do_something() won't be called.

PiMaster wrote:
BTW, chrisname, what do those last two Linux macros do?

They use gcc's builtin function __builtin_expect() to assist gcc with branch prediction.
1
2
3
4
5
if (expression) {
        if_true();
} else {
        if_false();
}

might compile to
1
2
3
cmp expression, 1
je if_true
jmp if_false

whereas
1
2
3
4
5
if (unlikely(expression)) {
        if_true();
} else {
       if_false();
}

would compile to
1
2
3
cmp expression, 0
je if_false
jmp if_true


Basically, it tells the compiler to order the branches so that the one that is more likely to be true is faster to jump to. If you're checking a variable in a loop, you can tell gcc that it's more likely that the variable will be equal to, say, 42 than any other value. With that knowledge, gcc can order your code so that it is faster to do what you said was more likely than it is to do anything else.

Example:
1
2
3
while (likely(x == 42)) {
        do_something_expensive();
}

might be faster than
1
2
3
while (x == 42) {
        do_something_expensive();
}

because in the first case, you're telling gcc that (x == 42) is going to be true more often than not.

GCC Documentation wrote:
— Built-in Function: long __builtin_expect (long exp, long c)

You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.

The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c. For example:

if (__builtin_expect (x, 0))
foo ();


would indicate that we do not expect to call foo, since we expect x to be zero. Since you are limited to integral expressions for exp, you should use constructions such as

if (__builtin_expect (ptr != NULL, 1))
error ();

http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
I use lots of these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define lambda(type,argsbody)\
  ({type _name_ argsbody &_name_;})
#define let(x,y) typeof(y) x=y
#define constfun(y) lambda(typeof(y),(void){return (y);})
#define defun(x,y) let(x,constfun(y))
#define swap(x,y) ({typeof(x) _z_=x;x=y;y=_z_;})
#define unless(x) if(!(x))
#define until(x) while(!(x))
#define cmalloc(n) (memclr(malloc(n),0,n))
#define foldmacro(l,n,f) ({\
	typeof(l[0]) a=l[0];\
	int i;\
	for(i=1;i<n;i++)a=f(a,l[i]);\
	a;\
})
#define mapmacro(x,y,n,f) ({\
	int i;\
	for(i=0;i<n;i++)y[i]=f(x[i]);\
})
#define foreach(x,a,n,code) ({\
	typeof(a[0]) *x=a;\
	int i;\
	for(i=0;i<n;x=a+(++i)){code;}\
})
#define safeswap(x,y) ({typeof(x) *xp=&x; typeof(y) *yp=&y; typeof(x) z=*xp;*xp=*yp;*yp=z;}) 
Last edited on
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))

That's basically it...I think I have some other ones but that's all I can remember off the top of my head.
#define trav(cont, it) for(typeof( cont.begin()) it=cont.begin(); it != cont.end(); it++) gcc extension.
#define _PRINT_INT_VALUE(pname) #pname << ": " << integerv(pname) <<endl used working in OpenGL for debug purpose
1
2
3
4
cout << _PRINT_INT_VALUE(GL_DOUBLEBUFFER)
		<< _PRINT_INT_VALUE(GL_STEREO)
		<< _PRINT_INT_VALUE(GL_AUX_BUFFERS)
		<< _PRINT_INT_VALUE(GL_RED_BITS);


swap? I prefer the function.
Last edited on
In C there isn't a swap function, and I tend to use only C when working with allegro because it interacts poorly. I use C++ when working with SDL.
Y'all ought to be shot.

Merry Christmas, BTW.
@ rocketboy9000

I use "swap" as a template function for swapping. If I were to include your header file in my project... you can imagine :)
I also like this one:
1
2
3
4
#define zalloc(size)				\
	do {					\
		calloc(size, 1)	\
	} while (0) 

Edit: Obviously it only works for char*.
Last edited on
I use "swap" as a template function for swapping. If I were to include your header file in my project... you can imagine :)


This is one of the bigger reason macros are evil.

You guys should at least be sticking to the ALLCAPS convention to minimize namespace corruption.


Also, chrisname, I don't get what zalloc does? Other than leak memory?
Disch wrote:
Also, chrisname, I don't get what zalloc does? Other than leak memory?

Oh yeah. It's supposed to just be an easier way of using calloc() for C strings but I didn't copy/paste it (I don't have most of these saved, they're stored in my brain), so I wrote it, evidently absent-mindedly.

Disch wrote:
You guys should at least be sticking to the ALLCAPS convention to minimize namespace corruption.

I only do that for values, i.e. #define BUFSZ 4096 ; for macro functions I always use lower case.
There is only one place where I use macros: when I have a bajillion very similar functions. Usually for tables of function pointers.
For example:
1
2
#define set_op(TP0, TP1, OP) Element TP0##TP1##OP (Element e0, Element e1){ TP0* a = (TP0*)e0.b; TP1* b = (TP1*)e1.b;
#define op(TP0, TP1, OP) TP0##TP1##OP 

then
1
2
3
4
5
6
set_op(Number, Number, add)
	Number* r = new Number();
	r->num = a->num * b->den + b->num * a->den;
	r->den = a->den * b->den;
	return r->simplify();
}

and then
1
2
3
typedef Element (*Operator) (Element, Element);
//...
Operator table[] = {op(Number, Number, add), op(Number, Base, mul), //and so on.. 
I don't use macros at all. It's also been frowned upon at several companies I consulted with.
I tend to stay away from them when I'm writing C++, but I write most of my code in C.
Topic archived. No new replies allowed.