53

Possible Duplicate:
What are C macros useful for?

Every few months I get an itch to go learn some bit of C that my crap college programming education never covered. Today it's macros. My basic understanding of macros is they're a simple search and replace that happens on your code prior to it being compiled. I'm having trouble understanding why you'd use macros. Most of the basic examples I'm looking at are something like

TEST(a,%d);
#define TEST(a,b) printf(" The value of " #a " = " #b " \n", a)

//which expands to 
printf(" The value of a = %d \n",a);

(example from here)

From my newbie point of view, it seems like defining a new function would give you the same results. I can see how historically macros would be useful for modifying a lot of source quickly in the days before easy search and replace, but something tells me I'm missing some bigger point.

So what kind of useful things can macros do for you?

Community
  • 1
  • 1
Alana Storm
  • 164,128
  • 91
  • 395
  • 599
  • 1
    Using macros the way you suggest (modifying existing source code by redefining existing tokens instead of actually changing the code) is a really bad idea, unless you're just talking about changing the values of #defined constants. – Tyler McHenry Aug 31 '09 at 16:53
  • 2
    Dupe of http://stackoverflow.com/questions/653839/what-are-c-macros-useful-for among many, many others. –  Aug 31 '09 at 17:01
  • 2
    Certainly similar to those questions, but none that came up in search directly asked what made macros superior to just defining a function to do the work for you. I'm much happier with the answers here than in that other thread. – Alana Storm Aug 31 '09 at 17:23
  • All of the answerrs that appear here have appeared in similar questions regarding macros - there are, after all, a limited number of things you can do with macros. –  Aug 31 '09 at 17:31
  • I disagree Neil. Quick example, this is the only thread that someone noted that macros can be used to avoid the creation of a new stack-frame, an answer that came about because the context of my question was different than the other questions. – Alana Storm Aug 31 '09 at 18:39
  • Which answer was that? And why to you think creating a stack-frame (you actually mean "calling a function") is a bad idea. And to say that this is not covered by the other answers is frankly ludicrous. –  Aug 31 '09 at 19:08
  • Harpos comments in the DeusAduro's answer mention the stack frame. I don't think it's either bad or good, I was just pointing out it's one additional piece of information I found useful and interesting that wasn't available in those other threads. Also, you may consider is "frankly ludicrous", but a google search (http://www.google.com/search?q=site%3Astackoverflow.com+c+macros+stack+frame) indicates if this fact did come up in another thread, it's pretty buried. – Alana Storm Aug 31 '09 at 19:27

11 Answers11

75

It's not exactly search and replace, it's token expansion. C macros are what every other kind of macro is in the computing world: a way to write something short and simple and have it automatically turn into something longer and more complicated.

One reason macros are used is performance. They are a way of eliminating function call overhead because they are always expanded in-line, unlike the "inline" keyword which is an often-ignored hint to the compiler, and didn't even exist (in the standard) prior to C99. For example, see the FD_ family of macros used in conjunction with the fd_sets used by select and pselect. These fd_sets are really just bitsets, and the FD_ macros are hiding bit twiddling operations. It would be annoying to write out the bit twiddling yourself every time, and a function call would be a lot of overhead for such a fast operation if it were not inlined.

Also, macros can do some things that functions cannot. Consider token pasting. Since the preprocessor runs before the compiler, it can make new identifiers for the compiler to use. This can give you a shorthand way to create lots of similar definitions, e.g.

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Another thing it can do that a function could not is turn compile-time information into runtime information:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

There's no way that a function could use the name of its parameter in its output like the macro can. This also demonstrates compiling out debug code for release builds.

Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
50

One reason is until C99, the inline keyword was not standard in the C language. Thus macros allowed you to inline small functions. They also in some ways work like templates, ie. you don't have to specify types in the macro definition eg:

#define MAX(x,y) ((x) > (y) ? (x) : (y))

This macro is complient with integers, doubles, floats etc.

DeusAduro
  • 5,971
  • 5
  • 29
  • 36
  • 2
    You should have parens around a and b on the right side. – i_am_jorf Aug 31 '09 at 16:39
  • 2
    This is a good point. Macros don't create an extra stack frame (unless of course you call a function from one). – harpo Aug 31 '09 at 16:42
  • Are inlines guaranteed to be inlined now? – Nosredna Aug 31 '09 at 16:53
  • 1
    @Nosredna: No, they aren't. In GCC anyway the compiler takes them as a strong hint but will still ignore you when it thinks it knows best. – Mike McQuaid Aug 31 '09 at 16:54
  • No. If anything, a modern compiler is more likely to ignore inline requests because of improved optimizing behavior within the compiler. – Tyler McHenry Aug 31 '09 at 16:55
  • 2
    Microsoft's compiler lets you say __forceinline to override the compiler. But you probably shouldn't be using it ever. Unless you're the kind of person who can look at the disassembly and say for certain one is better than the other. http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx – i_am_jorf Aug 31 '09 at 17:33
  • Well, I would look at the assembly, but more importantly, I time everything I do in C/C++ because the only thing I write in it anymore is DSP code. – Nosredna Aug 31 '09 at 18:47
17

Macros are expanded at compilation time. You are correct that they are often abused but a classic example in C would be to have a macro for writing debugging messages which (when debug mode is turned off at compilation time) doesn't generate any code so causes no slowdown.

Mike McQuaid
  • 9,615
  • 6
  • 33
  • 38
  • 3
    "Macros are expanded at compilation time." The preprocessor expands macros before the compiler even sees any code. – styfle Sep 01 '11 at 16:56
  • 5
    This is implementation detail. In principle, that can be taken as 2 phases of compilation (and if we looking deeper, almost any real life compiler does the work in many phases under the hood). – Display Name Mar 13 '13 at 12:13
13

Sometimes you want to do logging, but only in debug mode. So you write something like:

#ifdef DEBUG
#define LOG_MSG(x) printf(x);
#else
#define LOG_MSG(X)
#endif

Sometimes you just want to turn something off or on based on a compile-time switch. E.g., my company does some co-branding of our product and partners ask to turn things off. So we'll do something like:

#ifndef SPECIAL_PARTNER_BUILD
    DoSomethingReallyAwesome();
#endif

Then build with -DSPECIAL_PARTNER_BUILD when giving the partner drops.

Among many other possible reasons.

Sometimes you just want to save typing for things you do over and over again. Some people take this to far (cough MFC cough) and write what amounts to their own language in Macros to abstract away a difficult API. This makes debugging a frikkin' nightmare.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
  • Is it fair to say that, after the introduction of `inline`, this remains as the only "definitely use this" case? – llf Jan 25 '18 at 06:12
  • @t.y No? Constants are still widely used and it's better to just use `#def ANSWER_TO_EVERYTHING 42` instead of putting `42` everywhere. It's all fine and dandy until when one morning you wake up and realize that your 500k line project now wants to use `56` instead of `42` but instead of using a macro you hardcoded it everywhere, and a simple find and replace won't do because not all `42`'s might have been for the same thing and so need to be left as is. – Purple Ice Oct 29 '18 at 08:26
6

Macros can have many different uses other than function like things.

It is very useful to use macros for anything magic number or string related.

#define MY_MAGIC_NUM 57

/*MY_MAGIC_NUM used all through out the code*/
lillq
  • 14,758
  • 20
  • 53
  • 58
  • This sort of thing can increase the readability of your code. Also, it is pretty useful when defining the maximum size of a non-heap allocated array. – E.M. Aug 31 '09 at 16:53
  • Why is this preferred to using a constant? – Alana Storm Aug 31 '09 at 16:55
  • 1
    Wait, scratch that, I just realized constants ARE using macros in C. – Alana Storm Aug 31 '09 at 16:57
  • 1
    An array must be declared with a compile time constant expression. Unlike C++, `const` in C is never a compile time constant. (In C99, arrays inside functions can be declared with a variable size). – E.M. Aug 31 '09 at 17:05
  • 2
    No, there's a distinct difference between a global constant variable and a macro. Namely, the value of the macro is substituted into the code before compilation, while the value of the global constant is stored in the executable and loaded into memory and retrieved at execution time (optimizations notwithstanding). You can take the address of a global constant, but you cannot take the address of a macro. – Tyler McHenry Aug 31 '09 at 17:05
5

C macros can generate code at compile time. This can be (ab)used to effectively create domain-specific languages with new keywords and behaviors.

One of my favorite examples is Simon Tatham’s method of implementing coroutines in C through macros. The simplest macro implemented is:

#define crBegin static int state=0; switch(state) { case 0:

Yes, with an unmatched brace. Other macros will fix that up.

Dour High Arch
  • 21,513
  • 29
  • 75
  • 90
3

We used this type of macro in our code:

// convenience macros for implementing field setter/getter functions
#ifndef CREATE_GET_SET
#define CREATE_GET_SET(PREFIX, FIELD_NAME,FIELD_DATATYPE) \
  protected:\
    FIELD_DATATYPE PREFIX ## FIELD_NAME;\
  public:\
  inline FIELD_DATATYPE get ## _ ## FIELD_NAME(void) const\
  { \
    return(PREFIX ## FIELD_NAME); \
  } \
  inline void set ## _ ## FIELD_NAME(FIELD_DATATYPE p) \
  { \
    PREFIX ## FIELD_NAME = p; \
  }
#endif

within a class/structure you would define a variable:

CREATE_GET_SET(_, id, unsigned int);

This would define your variable and create the generic getter/setter for the code. It just makes for cleaner, consistent code generation for get/set. Sure, you can write it all out, but that's a lot of boilerplate type code NOTE: this is just one of a couple macros. I didn't post them all. You wouldn't handle say "char *" this way (where you want the set to strncpy or strcpy the data). This was just a simple demo of what you could do with a macro and some simple types.

jmq
  • 10,110
  • 16
  • 58
  • 71
1

In performance intense scenarios, you can use macros to create "automatic" loop unrolling. Modern compilers probably do a better job with this though, but that used to be a useful application for it.

korona
  • 2,308
  • 1
  • 22
  • 37
1

The compiler often knows details about the target machine, so you can use conditional compilation to have one piece of code for big endian processors and another for little endian processors. That keeps the code from being bloated with code that's designed for a different processor.

A similar case is when you have assembly code for one particular system but C code for other systems.

Nosredna
  • 83,000
  • 15
  • 95
  • 122
1

I think that biggest advantage comes when used as "setting file"

#define USE_FAST_AGORHITM
//#define USE_SLOW_ONE

And global "constants"

#define MAX_NUMBER_OF_USERS 100000

There are programs written mostly in macros (Check for instance Brian Gladman's AES implementation http://www.gladman.me.uk/cryptography_technology/index.php )

David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
Luka Rahne
  • 10,336
  • 3
  • 34
  • 56
0

On Macros, the function's code gets inserted into the caller's code stream. This can, depending on many other things, improve performance, because the optimizer can procedurally integrate the called code — optimize the called code into the caller But beware, because on macros argument types are not checked. A good reference to inline functions (if you are also using C++) and a little bit of macros is. http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5

Diego Dias
  • 21,634
  • 6
  • 33
  • 36