Cool macro tricks

Started by
73 comments, last by Mulligan 20 years, 7 months ago
What kind of unusual macros do any of yo use in your code?
Advertisement
Hehe, good one. Let''s see:

#define WIN32_LEAN_AND_MEAN#define DIRECTINPUT_VERSION 0x0800#define new new(_NORMAL_BLOCK,__FILE__, __LINE__)#define MSG_ERR(x) MessageBox(NULL, x, "Error!", MB_OK | MB_ICONSTOP)#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)#define ABS(a) (((a)<0) ? -(a) : (a))#define ZSGN(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0)

Not too original though
#define BINOUT(num,cast) {for(long n=sizeof(cast)*8;n--;cout<<!!(num&((cast)0x1<<n)));cout<<flush;}long a=10;BINOUT(a,char)  -> 00001010BINOUT(a,long)  -> 00000000000000000000000000001010


Was pretty usefull when debuging a small CRC application =)

[edited by - Wildfire on August 19, 2003 3:20:33 PM]
How do I set my laser printer on stun?
quote:
#define ABS(a) (((a)<0) ? -(a) : (a))#define ZSGN(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0) 

These macros are very dangerous. Consider:
#define ABS(a) (((a)<0) ? -(a) : (a))#define ZSGN(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0)int func(int arg){    return ABS(++arg);}int main(int argc, char** argv){    printf("func(5) is %d\n", func(5));    printf("func(-10) is %d\n", func(-10));    return 0;}

You are probably expecting each call to return 6 and 9, but they don''t. Why? The macro''s argument is inserted in the expansion every time the argument''s name (a) appears, and in this case is evaluated twice:
(((++arg)<0) ? -(++arg) : (++arg)) 

The argument is pre-incremented once during the comparison to zero, and once for either part of the conditional operator. They end up returning 7 and 8 respectively.

You can certainly go ahead and use macros like this all you want, but be very aware that they may have unintended side effects, and the programmer who follows in your footsteps (that''s you in six months) could get tripped up by it, even if you''re aware enough of it now to avoid problems.

If the macro were re-implemented as a regular (or inline) function, the pre-increment would be evaluated before the function is called, and would only happen once.

- dorix
I use this simple macro:

#define CLASSNAME(className) virtual const char *GetCassName() { return #className; }

It just adds virtual funtion to class that returns the class name. I use it in error messages.

class Test
{
public:
CLASSNAME(Test)
};
the # operator in the preprocessor is great for debugging. I use this little thing all the time

#define dump(x) std::cout << #x ": " << x

Not unusual, but very handy.
quote:Original post by stefu
I use this simple macro:

#define CLASSNAME(className) virtual const char *GetCassName() { return #className; }

It just adds virtual funtion to class that returns the class name. I use it in error messages.

class Test
{
public:
CLASSNAME(Test)
};


You could change that to this to write less code:
#define CLASS(className) class className { \public: \virtual const char * GetClassName() {return #className; } \private: 

It might not be as nice though

And I need to get a gnuwin32 grep...
for real great macro (and other coding) tricks, you can read up on the ASSERT statement that got set up on .. cuj i think.. or how ever.. of one of the c++ gurus and some other duded..

there, macros get used for real fun things!

"take a look around" - limp bizkit
www.google.com
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Here's something for you:
main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94,-27+t, a)&&t == 2 ?_<13 ?main ( 2, _+1, "%s %d %d\n" ):9:16:t<0?t<-72?main(_,t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"):t<-50?_==*a ?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a+1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

Note: Must be compiled with a C compiler (for VC++: File name must be .c, not .cpp), otherwise it doesn't work.

[edited by - Wildfire on August 19, 2003 4:07:09 PM]
How do I set my laser printer on stun?
I found a really weird macro in one of the DirectX SDK examples. I think it was the 3d text one.

On a bunch of strings, the code had something like: _T("string here")

So using Visual Assist, I checked what _T was:

#define _T(x) __T(x)

Okay, so I checked what __T was

#define __T(x) x

O________________________O

This topic is closed to new replies.

Advertisement