Archived

This topic is now archived and is closed to further replies.

Mulligan

Cool macro tricks

Recommended Posts

MindFlayer    262
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

Share this post


Link to post
Share on other sites
Wildfire    154

#define BINOUT(num,cast) {for(long n=sizeof(cast)*8;n--;cout<<!!(num&((cast)0x1<<n)));cout<<flush;}

long a=10;

BINOUT(a,char) -> 00001010
BINOUT(a,long) -> 00000000000000000000000000001010


Was pretty usefull when debuging a small CRC application =)

[edited by - Wildfire on August 19, 2003 3:20:33 PM]

Share this post


Link to post
Share on other sites
dorix    484
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

Share this post


Link to post
Share on other sites
stefu    120
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)
};

Share this post


Link to post
Share on other sites
tortoise    122
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.

Share this post


Link to post
Share on other sites
Leffe    301
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...

Share this post


Link to post
Share on other sites
davepermen    1047
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

Share this post


Link to post
Share on other sites
Wildfire    154
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]

Share this post


Link to post
Share on other sites
glassJAw    128
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

Share this post


Link to post
Share on other sites
stefu    120
Aother example of me uising macros
		

#define IF_INI_GET_VAR(ini,var,sect,attr) if (!ini.GetVar(sect,attr,var)) { cout<<"Error: Attribute '"<<attr<<"' not found or is empty in section ["<<sect<<"] in '"<<ini.get_filename()<<"'."<<endl; } else

// and code using this macro..


IF_INI_GET_VAR(parser,var,"LeftRearTyre","TyrePos")
m_tyre_setup[LeftRearTyre].m_tyre_pos = var.GetVec3();
IF_INI_GET_VAR(parser,var,"LeftRearTyre","TyreRadius")
m_tyre_setup[LeftRearTyre].m_radius = ma::abs(var.GetFloat());
IF_INI_GET_VAR(parser,var,"LeftRearTyre","Bump")
m_tyre_setup[LeftRearTyre].m_bump = ma::abs(var.GetFloat());
IF_INI_GET_VAR(parser,var,"LeftRearTyre","Rebound")
m_tyre_setup[LeftRearTyre].m_rebound = ma::abs(var.GetFloat());



Makes much cleaner look with all error reporting

[edited by - stefu on August 19, 2003 4:22:41 PM]

[edited by - stefu on August 19, 2003 4:23:52 PM]

Share this post


Link to post
Share on other sites
dorix    484
quote:
Original post by glassJAw
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
The _T macro is defined differently if you''re building a Unicode application. It''s to allow you to use string literals in your code (such as "string here") without needing to differentiate between ANSI string literals and Unicode string literals (such as L"string here"). Check out:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_unicode_programming_summary.asp.

- dorix

Share this post


Link to post
Share on other sites
ToohrVyk    1595

//MessageProcessingFunction...

//...Declare(Function Name)

//...Body(Engine, Function Name)


#define MessageProcessingFunctionDeclare(X) LRESULT CALLBACK X(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);

#define MessageProcessingFunctionBody(X,Y) LRESULT CALLBACK Y(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if(X) return exWindow::Messages(hwnd, msg, wparam, lparam); return DefWindowProc(hwnd, msg, wparam, lparam);}

//exWindowCreate(Height, Width, MessageHandler)


#define exWindowCreate(Z) WNDCLASSEX WindowClass; WindowClass.cbSize = sizeof(WNDCLASSEX); WindowClass.style = CS_HREDRAW | CS_VREDRAW; WindowClass.lpfnWndProc = Z; WindowClass.cbClsExtra = 0; WindowClass.cbWndExtra = 0; WindowClass.hInstance = hinstance; WindowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); WindowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW); WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); WindowClass.lpszClassName = "Extatica Main Window Class"; WindowClass.lpszMenuName = NULL; RegisterClassEx(&WindowClass); ShowCursor(true); HWND WinHandle; WinHandle = CreateWindowEx(NULL, "Extatica Main Window Class", "Extatica Engine", WS_OVERLAPPEDWINDOW| WS_VISIBLE, 160, 100, 320, 240, NULL, NULL, hinstance, NULL);

/*WS_POPUP | WS_VISIBLE, */
//SetupApplication(Pilot Class Name, Width, Height)


#define SetupApplication(P) exCore * ex = NULL; MessageProcessingFunctionDeclare(M) int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ exWindowCreate( M) ex = new exCore(); new P(); ex->Activate(WinHandle); return 0;} MessageProcessingFunctionBody(ex,M)


Use :

SetupApplication( Pilot ); creates an application, launches the extatica engine, and uses Pilot as the pilot.[/source]

ToohrVyk



[edited by - ToohrVyk on August 19, 2003 4:52:35 PM]

Share this post


Link to post
Share on other sites
jamessharpe    497
quote:
Original post by stefu
Aother example of me uising macros
		

#define IF_INI_GET_VAR(ini,var,sect,attr) if (!ini.GetVar(sect,attr,var)) { cout<<"Error: Attribute ''"<<attr<<"'' not found or is empty in section ["<<sect<<"] in ''"<<ini.get_filename()<<"''."<<endl; } else

// and code using this macro..


IF_INI_GET_VAR(parser,var,"LeftRearTyre","TyrePos")
m_tyre_setup[LeftRearTyre].m_tyre_pos = var.GetVec3();
IF_INI_GET_VAR(parser,var,"LeftRearTyre","TyreRadius")
m_tyre_setup[LeftRearTyre].m_radius = ma::abs(var.GetFloat());
IF_INI_GET_VAR(parser,var,"LeftRearTyre","Bump")
m_tyre_setup[LeftRearTyre].m_bump = ma::abs(var.GetFloat());
IF_INI_GET_VAR(parser,var,"LeftRearTyre","Rebound")
m_tyre_setup[LeftRearTyre].m_rebound = ma::abs(var.GetFloat());



Makes much cleaner look with all error reporting




This is dangerous. Look what happens if you put a semicolon at the end of the macro(an easy mistake). The function will still be executed even though an error has occured. This could cause a bug that could potentially only show it''s self in a released build. I doubt that most programmers would check the error code by removing each setting.

Share this post


Link to post
Share on other sites
jamessharpe    497
Here''s one for your math library

#ifdef DOUBLE_PRECISION
#define real double
#else
#define real float
#endif

then use real wherever you need a floating point value and you can then switch a compile time between precision.

Share this post


Link to post
Share on other sites
iNsAn1tY    476
Some crappy radians/degrees macros...
#define TORADIANS(Degrees) (Degrees * (PI / 180.0f))
#define TODEGREES(Radians) (Radians * (180.0f / PI))


Coding Stuff ->  [ iNsAn1tY Games | DarkVertex | How To Do CSG | Direct3D Vs. OpenGL | Google ]
Fun Stuff    ->  [ Evil T-Shirts | Stick-Based Comedy | You're Already Here | The Best Film Reviews ]


[edited by - iNsAn1tY on August 19, 2003 7:27:44 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I see that some of those macros are "dangerous". Well, go ahead, be lazy. Watch your feets.

Precompiler, one of those words that shouldn''t exist.

/__fold

Share this post


Link to post
Share on other sites
Beer Hunter    712

#define A atof
#define B strchr
#define C strstr
#define D ".."
float x, y, z[5];
#define double_int(a, b, c) (((((z[0]=0 \
,z [ \
1
] = A(B(#b,7*9- \
2 )+1),z[3]=A (B ( \
# c , 7 * 9 \
- 2 ) + 1)),z[2]=(A \
(C(#b,D)+2) - z [ 1 ] \
)/ 2 / 5 , z [ \
4
] =( A ( C ( \
# c,D)+2)-z[3 ])/2/5), z [ \
1
] = z [ 1 ] \
+ z [ 2 ]/ 2 \
, z [3]=z[3]+z[4]/2),R(a, 0 \
) , R( a , 1 \
) , R ( a , 2 \
) , R (a,3),R(a,4 ) , \
R ( a , 5 ),R(a,6),R( \
a , 7 ) , R( a \
, 8),R(a,9)), z [ 0 ] )
#define R(a, b) E (a , b , 0 ),E(a,b,1), \
E ( a ,b , 2 ) , \
E ( a,b,3),E(a, b , 4 ) \
, E ( a , b , 5 \
) , E ( a , b , \
6 ) , E (a,b,7), E ( \
a, b , 8 ) , E \
( a , b ,9 )
#define E(a, b, c) ( ( x =z[1]+(z[2] * \
b) , y = z \
[3]+(z[4]*c)),z[0]=z[0]+(a)*z[2]*z[10-6])

Share this post


Link to post
Share on other sites
GrinningGator    122
"Cool" and "macro" rarely are used in the same sentence. Assuming you''re programming in C++ (not C), inline functions often give you all the efficiency of a macro (no function call overhead) with none of the problems of a macro (mutliple argument evaluation, multiple line difficulties, no type-safety, etc.). Here''s what Marshall Cline has to say on the subject: link. Be sure to check out all the ways in which macros are "evil".

Here''s some inline functions that would replace many of the macros suggested above:
// not tested, use at your own risk

inline double MyAbs(double inDbl)
{
return (inDbl > 0.0 ? inDbl : -inDbl);
}
// you could make it generic with the use of a template

// and avoid writing an abs() function for floats,

// ints, shorts, etc.


const float PI = 3.1415926;

inline float ToRadian(float inDeg)
{
return inDeg * PI / 180.0f;
}

inline float ToDegrees(float inRad)
{
return inRad * 180.0f / PI;
}

// the rest are left as an excersize for the reader

Share this post


Link to post
Share on other sites
Yohumbus    152
Here is an awsome trick to make better assertions(too long to post so here is the article)

http://www.cuj.com/documents/s=8464/cujcexp0308alexandr/

Share this post


Link to post
Share on other sites
Desert Fox    277
I usually don''t use a macro unless all else fails, but sometimes they''re very useful. I use it in my logger to automatically insert line and file stamps into my log (also good for custom exceptions, assertions, etc.) I also use macros to generate my own custom enum that contains a little more debugging info, supports some other nifty things, etc. Macros are generally "evil" (especially ones with common names a la the Win32 API. At least name your macros in all uppercase letters...) They have their place, you just have to know when and where to use them

desertfox

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
GrinningGator: inline/__force inline only works in VS pro ed or?

/__fold

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
GrinningGator: inline/__force inline only works in VS pro ed or?

/__fold

Share this post


Link to post
Share on other sites
Shannon Barber    1681
quote:
Original post by glassJAw
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




That''s so you can have one code base that will compile for ansi and unicode. When UNICODE is defined, I think __T(x) is defined as L##x.

Share this post


Link to post
Share on other sites