32

What C macro is in your opinion is the most useful? I have found the following one, which I use to do vector arithmetic in C:

#define v3_op_v3(x, op, y, z) {z[0]=x[0] op y[0]; \ z[1]=x[1] op y[1]; \ z[2]=x[2] op y[2];} 

It works like that:

v3_op_v3(vectorA, +, vectorB, vectorC); v3_op_v3(vectorE, *, vectorF, vectorJ); ... 
7
  • 3
    And you're not implementing any of the standard forms of vector multiplication here (not dot product, cross product, nor tensor product). Commented Nov 20, 2009 at 18:07
  • 1
    Component-wise multiplication has it's uses, but the dimensional limit imposed by the macro makes it not so useful. Commented Nov 20, 2009 at 18:17
  • 1
    @outis: This is intended to be used in areas where the dimensional limit is strictly imposed by the very nature of the application area. Like in 3D graphics, for example. Commented Nov 20, 2009 at 18:30
  • 34
    But suppose it the number of dimensions in the universe changes, the code will break - this is the sort of shortsightedness that led to the Y2K problem. Commented Nov 20, 2009 at 18:41
  • 8
    Yeah... It like that famous quote from Xerox manual. One of the benefits of declaring PI as a named constant is that it helps you to adjust the code in case the value of Pi changes. Commented Nov 20, 2009 at 19:09

18 Answers 18

36
#define IMPLIES(x, y) (!(x) || (y)) #define COMPARE(x, y) (((x) > (y)) - ((x) < (y))) #define SIGN(x) COMPARE(x, 0) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) #define SWAP(x, y, T) do { T tmp = (x); (x) = (y); (y) = tmp; } while(0) #define SORT2(a, b, T) do { if ((a) > (b)) SWAP((a), (b), T); } while (0) #define SET(d, n, v) do{ size_t i_, n_; for (n_ = (n), i_ = 0; n_ > 0; --n_, ++i_) (d)[i_] = (v); } while(0) #define ZERO(d, n) SET(d, n, 0) 

And, of course, various MIN, MAX, ABS etc.

Note, BTW, that none of the above can be implemented by a function in C.

P.S. I would probably single out the above IMPLIES macro as one of the most useful ones. Its main purpose is to facilitate writing of more elegant and readable assertions, as in

void foo(int array[], int n) { assert(IMPLIES(n > 0, array != NULL)); ... 
Sign up to request clarification or add additional context in comments.

21 Comments

Your macro-fu is impressive (you parenthesize correctly and know the do...while(0) technique), but there's still multiple evaluation problems that you really can't fix.
@David Thornley: "Multiple evaluation" with macros is what also gives us "lazy evaluation". It is as much of a problem as it is a feature. One just has to learn to use it properly. To say that danger of "multiple evaluation" somehow means that one shall not use macros, is exactly the same as to say that one shall not use division operator because there's a danger of dividing something by zero.
@Tomas: there's no need, but your way means that callers who want to do SWAPINT(*xp, *yp) now need to check xp != yp first. These days I don't see much point in adding an awkward edge case in order to (maybe) save a register and/or 4 bytes of stack.
Nice, liking "IMPLIES" the most :)
@JPMC: SET simply assigns the given value v to all n elements of array d. ZERO uses SET to assign value 0 to all n elements of array d.
|
23

The key point with C macros is to use them properly. In my mind there are three categories (not considering using them just to give descriptive names to constants)

  1. As a shorthand for piece of codes one doesn't want to repeat
  2. Provide a general use function
  3. Modify the structure of the C language (apparently)

In the first case, your macro will live just within your program (usually just a file) so you can use macros like the one you have posted that is not protected against double evaluation of parameters and uses {...}; (potentially dangerous!).

In the second case (and even more in the third) you need to be extremely careful that your macros behave correctly as if they were real C constructs.

The macro you posted from GCC (min and max) is an example of this, they use the global variables _a and _b to avoid the risk of double evaluation (like in max(x++,y++)) (well, they use GCC extensions but the concept is the same).

I like using macros where it helps to make things more clear but they are a sharp tool! Probably that's what gave them such a bad reputation, I think they are a very useful tool and C would have been much poorer if they were not present.

I see others have provided examples of point 2 (macros as functions), let me give an example of creating a new C construct: the Finite state machine. (I've already posted this on SO but I can't seem to be able to find it)

 #define FSM for(;;) #define STATE(x) x##_s #define NEXTSTATE(x) goto x##_s 

that you use this way:

 FSM { STATE(s1): ... do stuff ... NEXTSTATE(s2); STATE(s2): ... do stuff ... if (k<0) NEXTSTATE(s2); /* fallthrough as the switch() cases */ STATE(s3): ... final stuff ... break; /* Exit from the FSM */ } 

You can add variation on this theme to get the flavour of FSM you need.

Someone may not like this example but I find it perfect to demonstrate how simple macros can make your code more legible and expressive.

2 Comments

looks more like VHDL or so :)
you are an evil evil person lol
20

for-each loop in C99:

#define foreach(item, array) \ for(int keep=1, \ count=0,\ size=sizeof (array)/sizeof *(array); \ keep && count != size; \ keep = !keep, count++) \ for(item = (array)+count; keep; keep = !keep) int main() { int a[] = { 1, 2, 3 }; int sum = 0; foreach(int const* c, a) sum += *c; printf("sum = %d\n", sum); // multi-dim array int a1[][2] = { { 1, 2 }, { 3, 4 } }; foreach(int (*c1)[2], a1) foreach(int *c2, *c1) printf("c2 = %d\n", *c2); } 

5 Comments

This is so easy to misuse when your array suddently becomes heap-allocated...
@Alexandre C. just as easy to misuse as the manual sizeof-with-forloop way. I suspect one better double checks all actions in C :)
Yes, my comment was directed to the idiom, not to the macro.
What is the purpose of the keep variable, and why does foreach expand to a nested for loop?
@ToddLehman the purpose is to make break work (and my code was broken. I thought I copied it from a different answer of me, but apparently I wasn't quite enough awake :p. I fixed it, please double-check)
12

If you need to define data multiple times in different contexts, macros can help you avoid have to relist the same thing multiple times.

For example, lets say you want to define an enum of colors and an enum-to-string function, rather then list all the colors twice, you could create a file of the colors (colors.def):

c(red) c(blue) c(green) c(yellow) c(brown) 

Now you can in your c file you can define your enum and your string conversion function:

enum { #define c(color) color, # include "colors.def" #undef c }; const char * color_to_string(enum color col) { static const char *colors[] = { #define c(color) #color, # include "colors.def" #undef c }; return (colors[col]); }; 

1 Comment

7
#if defined NDEBUG #define TRACE( format, ... ) #else #define TRACE( format, ... ) printf( "%s::%s(%d)" format, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__ ) #endif 

Note that the lack of a comma between "%s::%s(%d)" and format is deliberate. It prints a formatted string with source location prepended. I work in real-time embedded systems so often I also include a timestamp in the output as well.

4 Comments

Shouldn't the NDEBUG one be #define TRACE (format, ...) ((void)0) to avoid traps like if(cond) TRACE(...) ?
@Gregory : What is the "trap"? If you failed to place a semi-colon after the macro call, it is probably wrong in any case - if(x) TRACE("y = %d", y ); would resolve to if(x); which will have no effect.
My bad... I was pretty sure at one point I used a compiler for which ; wasn't a valid statement but it's not a problem for GCC. assert.h still seems to use #define assert(ignore)((void) 0) though.
That's because the C standard mandates that assert expand to a void expression, regardless of the value of NDEBUG
6

Foreach loop for GCC, specifically C99 with GNU Extensions. Works with strings and arrays. Dynamically allocated arrays can be used by casting them to a pointer to an array, and then dereferencing them.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #define FOREACH_COMP(INDEX, ARRAY, ARRAY_TYPE, SIZE) \ __extension__ \ ({ \ bool ret = 0; \ if (__builtin_types_compatible_p (const char*, ARRAY_TYPE)) \ ret = INDEX < strlen ((const char*)ARRAY); \ else \ ret = INDEX < SIZE; \ ret; \ }) #define FOREACH_ELEM(INDEX, ARRAY, TYPE) \ __extension__ \ ({ \ TYPE *tmp_array_ = ARRAY; \ &tmp_array_[INDEX]; \ }) #define FOREACH(VAR, ARRAY) \ for (void *array_ = (void*)(ARRAY); array_; array_ = 0) \ for (size_t i_ = 0; i_ && array_ && FOREACH_COMP (i_, array_, \ __typeof__ (ARRAY), \ sizeof (ARRAY) / sizeof ((ARRAY)[0])); \ i_++) \ for (bool b_ = 1; b_; (b_) ? array_ = 0 : 0, b_ = 0) \ for (VAR = FOREACH_ELEM (i_, array_, __typeof__ ((ARRAY)[0])); b_; b_ = 0) /* example's */ int main (int argc, char **argv) { int array[10]; /* initialize the array */ int i = 0; FOREACH (int *x, array) { *x = i; ++i; } char *str = "hello, world!"; FOREACH (char *c, str) printf ("%c\n", *c); /* Use a cast for dynamically allocated arrays */ int *dynamic = malloc (sizeof (int) * 10); for (int i = 0; i < 10; i++) dynamic[i] = i; FOREACH (int *i, *(int(*)[10])(dynamic)) printf ("%d\n", *i); return EXIT_SUCCESS; } 

This code has been tested to work with GCC, ICC and Clang on GNU/Linux.

Lambda expressions (GCC only)

#define lambda(return_type, ...) \ __extension__ \ ({ \ return_type __fn__ __VA_ARGS__ \ __fn__; \ }) int main (int argc, char **argv) { int (*max) (int, int) = lambda (int, (int x, int y) { return x > y ? x : y; }); return max (1, 2); } 

Comments

6

Someone else mentioned container_of(), but didn't provide an explanation for this really handy macro. Let's say you have a struct that looks like this:

struct thing { int a; int b; }; 

Now if we have a pointer to b, we can use container_of() to get a pointer to thing in a type safe fashion:

int *bp = ...; struct thing *t = container_of(bp, struct thing, b); 

This is useful in creating abstract data structures. For example, rather than taking the approach queue.h takes for creating things like SLIST (tons of crazy macros for every operation), you can now write an slist implementation that looks something like this:

struct slist_el { struct slist_el *next; }; struct slist_head { struct slist_el *first; }; void slist_insert_head(struct slist_head *head, struct slist_el *el) { el->next = head->first; head->first = el; } struct slist_el slist_pop_head(struct slist_head *head) { struct slist_el *el; if (head->first == NULL) return NULL; el = head->first; head->first = el->next; return (el); } 

Which is not crazy macro code. It will give good compiler line-numbers on errors and works nice with the debugger. It's also fairly typesafe, except for cases where structs use multiple types (eg if we allowed struct color in the below example to be on more linked lists than just the colors one).

Users can now use your library like this:

struct colors { int r; int g; int b; struct slist_el colors; }; struct *color = malloc(sizeof(struct person)); color->r = 255; color->g = 0; color->b = 0; slist_insert_head(color_stack, &color->colors); ... el = slist_pop_head(color_stack); color = el == NULL ? NULL : container_of(el, struct color, colors); 

Comments

5
#define COLUMNS(S,E) [ (E) - (S) + 1 ] struct { char firstName COLUMNS ( 1, 20); char LastName COLUMNS (21, 40); char ssn COLUMNS (41, 49); } 

Save yourself some error prone counting

1 Comment

thanks, very useful actually! (you have forgotten the types in your example)
4

This one is from linux kernel (gcc specific):

#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) ); }) 

Another missing from other answers:

#define LSB(x) ((x) ^ ((x) - 1) & (x)) // least significant bit 

3 Comments

The name for the last macro is pretty confusing. LSB evokes (x) & 1.
The latter should be LSSB -- least significant set bit
Or LSD - Least significant digit, though I fear that may have negative conotations...
2

I also like this one:

#define COMPARE_FLOATS(a,b,epsilon) (fabs(a - b) <= epsilon * fabs(a)) 

And how you macros-haters do fair floating-point comparisons?

21 Comments

"how you macros-haters do fair floating-point comparisons" static inline function.
There is not such thing as "macro hater". Every time you see a "macro heater", it is in reality a beginner that is trying to present himself as more mature programmer than he really is by parroting what he thinks sounds as "mature" maxima.
@AndreyT: Given that I'm a macro hater, would you care to estimate how many years I've worked professionally in C and C++, and how many courses I've taught at the University level on programming in C?
I hate macros too. I also hate lawnmowers - I generally acknowledge the need for shorter grass, I just don't enjoy the process of using the one to achieve the other. I've used macros in another language which were much richer (for instance you could loop without resorting to a recursive include) and yet which were also easier to use correctly than C macros.
@David Thornley: Is it relevant? A grandma that was driving from her house to her favorite grocery store for 40 years technically has 40 years of driving experience. Does that make her a good driver? Good programmers never hate anything, since absolutely everything has its time and place.
|
2

Just the standard ones:

#define LENGTH(array) (sizeof(array) / sizeof (array[0])) #define QUOTE(name) #name #define STR(name) QUOTE(name) 

but there's nothing too spiffy there.

5 Comments

Aside: someone posted a LENGTH macro from Google that would cause a compile time error if passed a pointer, but I haven't been able to find it again. Does anyone know the macro and have a link to the answer (or another page) that shows it?
This one works for one-dimensional arrays, but you need to pass it the element type: #define REQUIRE_ARRAY(T, X) (void)(sizeof (((char(*)(T(*)[]))0)(&(X))))
The following works in C99 also for dimensions greater than 1. You need to call REQUIRE_ARRAY2 for an array with 2 dimensions, for example: #define REQUIRE_ARRAY2(T, X) (void)(sizeof (((char(*)(T(*)[*][*]))0)(&(X))))
@outis - Quite late to the party, but I believe #define IS_ARRAY(a) ((void *)&a == (void *)a) works as a runtime test for whether something is an array or a pointer (unless the pointer is pointing to itself, which may happen as part of a circularly linked structure, but is somewhat uncommon).
The party never ends. The Google LENGTH macro may have been the one posted by Michael Burr in answer to "Common array length macro for C?". Note that it's not a test whether something is an array but a macro that results in the length of an array or an error for other types.
2
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) 

Find the closest 32bit unsigned integer that is larger than x. I use this to double the size of arrays (i.e. the high-water mark).

1 Comment

Wouldn't it be faster and simpler to use __builtin_clz and a single shift?
1

also multi-type Minimum and Maximum like that

//NOTE: GCC extension ! #define max(a,b) ({typeof (a) _a=(a); typeof (b) _b=(b); _a > _b ? _a:_b; }) #define min(a,b) ({typeof (a) _a=(a); typeof (b) _b=(b); _a < _b ? _a:_b; }) 

9 Comments

It's so short, it's scary. Also, this is a textbook example of why not to use macros. (because the arguments are (conditionally) evaluated multiple times)
I think, there was gcc extension for min/max. Something like a >? b
@Justin: Huh? The above code uses GCC extensions specifically to avoid multiple evaluations. There's no multiple evaluatuion in the above.
@Xeor: Those were g++ extensions and have been deprecated since gcc 4.0. gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/…
@Hernán, and what is with four parameters? I'd go for max(max(a, b), c) instead
|
1

Checking whether a floating point x is Not A Number:

#define ISNAN(x) ((x) != (x)) 

4 Comments

again, why not implement this as an (inline) function?
@nikie because the C99 inline specification for functions is not supported by many compilers.
@Remo: it's very widely supported, it just isn't always called inline.
@nikie: if you're using C99 features (inline), just use the C99 isnan( ) macro defined in <math.h>.
1

Pack bytes,words,dwords into words,dwords and qwords:

#define ULONGLONG unsigned __int64 #define MAKEWORD(h,l) ((unsigned short) ((h) << 8)) | (l) #define MAKEDWORD(h,l) ((DWORD) ((h) << 16)) | (l) #define MAKEQWORD(h,l) ((ULONGLONG)((h) << 32)) | (l) 

Parenthesizing arguments it's always a good practice to avoid side-effects on expansion.

2 Comments

You should typedef ULONGLONG: typedef unsigned __int64 ULONGLONG;
Isn't MAKEQWORD wrong? Should cast h to ULONGLONG before shifting, not after.
0

This one is awesome:

#define NEW(type, n) ( (type *) malloc(1 + (n) * sizeof(type)) ) 

And I use it like:

object = NEW(object_type, 1); 

7 Comments

What's with the 1+ allocating an extra byte for every allocation?
And why the cast? Never use that cast on the result of malloc() or related function. It takes time to type, and the only time it does anything is if you forgot to #include <stdlib.h>. If I do that, I'd rather have the diagnostic than have stuff continue to probably work.
The macro's named NEW—seems pretty clear to me it might allocate memory. Also, the cast is needed for C++, which will not implicitly convert a void * to another type.
@LnxPrgr3: If you're writing in C++: DON'T DO THAT! Use new instead, and never use macros like this.
This failing to work in C++ is arguably a feature. It tells you that you've mistakenly run the wrong compiler. If you really want to compile your C with a C++ compiler, you could always define different versions of the macro according to whether __cplusplus is set. Using this macro at all in genuine C++ is questionable, and calling it NEW in C++ when it has nothing to do with new probably isn't a good plan.
|
0

One (of the very few) that I use regularly is a macro to declare an argument or variable as unused. The most compatible solution to note this (IMHO) varies by compiler.

1 Comment

can you show us a typical example?
-1

TRUE and FALSE seem to be popular.

3 Comments

And misused. It's too bad that C doesn't have a real boolean type, like C++ or Java.
C99 has a bool type, stdbool.h
I see if (var == TRUE) way too often and refuse to use these.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.