Archived

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

Sinner_Zero

Macro(???????????)

Recommended Posts

Ok, ok, ok. Can someone explain macros to me, I use them and all but what exacly are the specifics on them? possibly a tutorial link if it''s so complicated. Any help is greatly appreciated.

Share this post


Link to post
Share on other sites
A macro is a symbol whose definition is substituted everywhere it occurs before compilation. The compilation process for a C/C++ source file includes a stage called "preprocessing." It is the preprocessor that handles all those keywords that begin with the hash symbol (#). #include, for example, causes the preprocessor to place the entire included file in place. #define causes an environment symbol to be created (and its value to be substituted everywhere it is referenced in code), which is the basis of macros. Here''s an example:
#define deg2rad(x) (M_PI/180 * x) 

Now everywhere in the same file (or files that include this file) where the program sees deg2rad(v) - where v is any value - the preprocessor will substitute (M_PI/180 * v) in its place (note that M_PI is also a "macro" of sorts; it''s a defined symbol). Now if v was a non-numeric value like a string
int y = deg2rad("a"); 

the compiler will puke where it''s trying to multiply numbers and a string. Unfortunately, that would be the line where the macro was defined, so tracking down the bug would be pretty hard. You see, macros don''t do type-checking, so you can get some very bizarre behavior (which will sometimes compile but crash hard during execution).

If you''re using C++, use inline functions instead (and use const for constant values):
#ifndef M_PI // some platforms define M_PI
const float M_PI = 3.1459;
#endif
inline float deg2rad(float f) { return (180 / M_PI) * f; }

The problem with this as opposed to macros is that if you pass it an integer, you''ll get a type mismatch. However, since you''re using C++ you might as well make it a template function:
inline template <typename T> T deg2rad(T val) { return (180 / M_PI) * val; } 


In conclusion, if you''re a C++ programmer, stick to inlines and const values; they were designer specifically to combat the shortcomings of macros and defines.

Share this post


Link to post
Share on other sites
I am C++ guy, but you see all these people demand C instead, so I haveto get used to doing all of this C stuff, hell my whole Win32 book is C and freakin' UNICODE compliance, damn code nazis.

Ok, um, thnx a ton for the explanation, but I got one more thingy thats sorta bothering.

#define __T(x) L##x    

Makes a call to __T("Hello!") into a call to L"Hello!" is what this book says. Ummm... does this make sense to you? is this L## thing what I think it is. In which case can I then do like

#define MYCRAZYCRAP##x __T(x)    

that way I can do MYCRAZYCRAP"Hello!" which would actually do __T("Hello!") which would actually do L"Hello!"

If thats not the way to define such a thing is there a way?

And can anyone tell me if the Bjorne guys C++ reference would cover all of this, I mean it would right? Cuz I'm thinking of buying that and with it the STL book that amazon recommends. Anyone?

Edited by - Sinner_Zero on November 17, 2001 8:40:39 PM

Share this post


Link to post
Share on other sites
The ## preprocessor directive is used to concatenate the tokens before and after it. It's not very useful under most circumstances. Here's an example of how it works:
    
#define concat(a, b) a##b

int main() {
int xy = 10;
cout << conat(x,y);
}

The preprocessor transforms
cout << concat(x,y);
int
cout << xy;
which prints 10.

-Neophyte

EDIT: Formatting
- Death awaits you all with nasty, big, pointy teeth. -

Edited by - Neophyte on November 17, 2001 8:45:12 PM

Share this post


Link to post
Share on other sites
Bjarne Stroustrup''s book "The C++ Programming Language" cover''s a lot technical, but it doesn''t go much into depth with C technicalities (like how to do asm in C and such), and neither does it go into depth with STL technicalities, i''d recommend for pure C getting Kernighan and Richie''s "The C Programming Language" and P.J. Plauger''s "The C++ Standard Template Library"

Share this post


Link to post
Share on other sites
There is little about macros in the Stroustrup (3rd ed).
I''d advise you to buy also Herbert Schildt "C/C++ Programmer''s Reference (2nd ed)", published by Osborne.

As for ##, it indeed does token concatenation :

  
#define CAT( X, Y ) X##Y

CAT( 2, 3 ) is 23
CAT( A, 5 ) is A5


But, IMHO, more interesting is # which can be very useful to print debugging statements :

  
#define STR( X ) #X
STR( x ) is "x"

#define DBG( X ) X; //
{ if( debug_mode ) std::cerr << #X << std::endl; }

Share this post


Link to post
Share on other sites
quote:
Original post by abdulla
Bjarne Stroustrup''s book "The C++ Programming Language" cover''s a lot technical, but it doesn''t go much into depth with C technicalities (like how to do asm in C and such)...


Assembly language is not a standard part of C or C++, it is an extension added by the compiler. That''s probably why he doesn''t cover it .

[Resist Windows XP''s Invasive Production Activation Technology!]

Share this post


Link to post
Share on other sites
That and the publisher sems to be McGraw here.....hmmm, maybe I''m dumb.

Thnx, I think I''ll really buy that one, especially since you say ALSO and not NO JUST BUY THIS.

That and it''s cheap =)

Share this post


Link to post
Share on other sites
Imagine you want to print what piece of code is executed as it is executed. One way to do it is to create a string mirroring the code and printing it out :

    
{
foo = bar + baz;
if (debug) std::cerr << "foo = bar + baz" << std::endl;
}


However, you have to take care to keep the string and the code in synch. Well, that is what the # macro is for : it converts source code into a string that the source code can use.

    

#define STRING( X ) #X

{
foo = bar + baz;
if (debug) std::cerr << STRING(foo = bar + baz) << std::endl;
}




Which would not buy you much if you couldn't do things with X within the macro itself :

    

#define DBG( X ) { X; if( debug ) std::cerr << #X << std::endl; } /* Executes and prints X */

{
DBG( foo = bar + baz );
}


This is what is used in the assert( X ) macro. It tests the value of the expression X, and if it is false, it prints it out and abort().

Edited by - Fruny on November 17, 2001 12:10:13 AM

Share this post


Link to post
Share on other sites
quote:
Original post by Sinner_Zero
whats that X for???

To do X.

Remember that X does not necessarily have to be a single variable; it can be a statement (which the preprocessor simply substitutes in place.) For example, in Fruny''s example
foo = bar + baz 

is X. The macro therefore ensures that X is executed, and then only if debug is specified is the rest executed.

Share this post


Link to post
Share on other sites
IC, X isnt really done since the macro screws it all then.

so the macro hasto actually do X, cool. this stuff is neat.

THNX a ton once again guys, the more I know. heh.

Share this post


Link to post
Share on other sites