views:

904

answers:

19

What C-macros is in your opinion is the most useful? I have found the following one, which I use to do vector arithmetics 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);
...
A: 

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; })
psihodelia
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)
Justin
*or* (haven't had enough coffee) you're working with copied objects
Justin
I think, there was gcc extension for min/max. Something like `a >? b`
Xeor
@Justin: If you're going to work with copied objects, you may as well use functions. This is not something that can be effectively done with C macros.
David Thornley
@Justin: Huh? The above code uses GCC extensions specifically to avoid multiple evaluations. There's no multiple evaluatuion in the above.
AndreyT
@Xeor: Those were g++ extensions and have been deprecated since gcc 4.0.http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Min-and-Max.html#Min-and-Max
jamessan
also three parameter version, useful sometimes:#define max(a,b,c) (a) > (b) ? ((a) > (c) ? (a) : (c)) : ((b)>(c) ? (b) : (c))
Hernán
@Hernán, and what is with four parameters? I'd go for max(max(a, b), c) instead
quinmars
@quinmars: that's also ok -- but I use C++ inlines and templates, anyway ;)
Hernán
A: 

In my opinion most macros should be forbidden, make a normal function out of that code, otherwise you can have some problems that you won't be able to find due to the preprocessor work.

Simon
it is not a polite answer :)
psihodelia
macroses are very usefull if you deal with embedded systems
psihodelia
and I think it's not right too. There are things you can do with macros that you can't do with functions.The fact that somebody could abuse macros it's not an argument for suggesting they should be forbidden
Remo.D
I would say you are right if C were a more expressive language. But sometimes macros are the only way to go if you don't want to repeat yourself (which is a Bad Thing).
fortran
A meaningless answer. It is not possible to make "a function" from a macro in general case. Macros are extremely valuable tool which is not in any way replaceable with functions.
AndreyT
-1 That's your opinion, but it doesn't qualify as a good answer.
qrdl
Look at my foreach loop anwser for an example of something that *cannot* be done with macros.
Joe D
A: 

This one is awesome:

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

And I use it like:

object = NEW(object_type, 1);
psihodelia
What's with the `1+` allocating an extra byte for every allocation?
John Ledbetter
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.
David Thornley
malloc in a macro? are you serious? Noone will ever know where that memory leak came from.
Johannes Rudolph
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
@LnxPrgr3: If you're writing in C++: DON'T DO THAT! Use `new` instead, and never use macros like this.
David Thornley
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.
Steve Jessop
+1  A: 

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?

psihodelia
Why would you use a macro instead of a function for that? And what happens when you use 'COMPARE_FLOATS(a,b-x,eps)'?
nikie
Not to mention this fails badly if a is 0.0.
David Thornley
"how you macros-haters do fair floating-point comparisons" static inline function.
Steve Jessop
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
That's fine if you want to compare them incorrectly. Here's how to do it right: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Dr. Tim
@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?
David Thornley
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.
Steve Jessop
@Steve: Yes, I suppose I should clarify. I hate C macros. I love Lisp macros.
David Thornley
Certainly proves your academic credentials ;-)
Steve Jessop
@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.
AndreyT
@Andrey: actually it is relevant. That grandmother is not a "beginner". You asserted that every macro-hater is a beginner, not that every macro-hater is a bad programmer. But even pretending you'd said "non-good" in the first place, it's absurd. Acknowledging the necessity of a technique, and using it correctly, is not identical with liking it, and you can still be annoyed there isn't something better. Further, if it were true that good programmers believe everything has its time and place, then no good programmer would ever deprecate or remove any feature in a new release.
Steve Jessop
But anyway, I think this has now fully descended to the "no true Scotsman" argument. Andrey says, "no good programmer disagrees with me". David says, "I'm a good programmer, and I disagree with you". Andrey says, "but if you disagree with me, then you cannot possibly be a good programmer".
Steve Jessop
@Steve: Features don't get deprecated out of pure hate. No programmer would ever deprecate a feature until an adequate replacement feature is implemented.
AndreyT
But the reason you develop a replacement might well be that you hate the original.
Steve Jessop
I love macros, but I do my floating-point comparisons the way god intended -- strict equality.
Stephen Canon
Btw, noted "bad programmer" Jon Skeet hates the "lock" statement in C# ;-p
Steve Jessop
Sorry, forgot the link: http://stackoverflow.com/questions/282329/what-are-five-things-you-hate-about-your-favorite-language/282342#282342
Steve Jessop
A: 

Checking whether a floating point x is Not A Number:

#define ISNAN(x) ((x) != (x))
psihodelia
again, why not implement this as an (inline) function?
nikie
@nikie because the C99 inline specification for functions is not supported by many compilers.
Remo.D
@Remo: it's very widely supported, it just isn't always called `inline`.
Steve Jessop
@nikie: if you're using C99 features (`inline`), just use the C99 `isnan( )` macro defined in `<math.h>`.
Stephen Canon
A: 

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.

outis
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?
outis
Johannes Schaub - litb
Johannes Schaub - litb
+16  A: 
#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));
  ...
AndreyT
very nice, but I still cannot vote, sorry :(
psihodelia
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
@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.
AndreyT
No need for a temp-var when swapping integers: #define SWAPINT(x, y) do { (x) ^= (y); (y) ^= (x); (x) ^= (y); } while(0)
Tomas
@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.
Steve Jessop
@Ramónster: No, I couldn't. Do a search on it, it is a known trick and a popular question. For example, think what will happen to `if (condition) SWAP(a, b, int); else /* something */;` with my version and with yours.
AndreyT
@AndreyT: imperfect analogy. There are no operators that _look_ like division operators yet cause an error when dividing by one or two. That said, I don't have anything against macros, and the `IMPLIES` is really nice.
int3
Nice, liking "IMPLIES" the most :)
Johannes Schaub - litb
+9  A: 

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.

Remo.D
looks more like VHDL or so :)
psihodelia
you are an evil evil person lol
Earlz
+3  A: 
#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

EvilTeach
thanks, very useful actually! (you have forgotten the types in your example)
psihodelia
Yep, late friday afternoon effect.Thank you
EvilTeach
A: 

TRUE and FALSE seem to be popular.

T.E.D.
And misused. It's too bad that C doesn't have a real boolean type, like C++ or Java.
David Thornley
C99 has a bool type, stdbool.h
srparish
+2  A: 

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
Alexandru
avakar
The latter should be LSSB -- least significant set bit
Chris Dodd
Or LSD - Least significant digit, though I fear that may have negative conotations...
Joe D
+4  A: 

for-each loop in C99:

#define foreach(item, array) \
    for(int keep=1, \
            count=0,\
            size=sizeof (array)/sizeof *(array); \
        count != size; \
        keep=1, 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);
}
Johannes Schaub - litb
This is so easy to misuse when your array suddently becomes heap-allocated...
Alexandre C.
@Alexandre C. just as easy to misuse as the manual `sizeof`-with-forloop way. I suspect one better double checks all actions in C :)
Johannes Schaub - litb
@Johannes: Yes, my comment was directed to the idiom, not to the macro.
Alexandre C.
A: 

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.

Justin
can you show us a typical example?
EvilTeach
A: 
#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).

A: 

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.

Hernán
You should typedef ULONGLONG: `typedef unsigned __int64 ULONGLONG;`
strager
Isn't MAKEQWORD wrong? Should cast h to ULONGLONG before shifting, not after.
Dipstick
A: 

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);
}
Joe D
+2  A: 
#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.

Clifford
+1  A: 

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);

Where this is useful is in creating abstract data structures. For example, rather then 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's it'll give you good compiler line-numbers on errors, works nice with the debugger. It's also pretty typesafe, except for the case where your datatypes are used multiple types in the same struct (eg if we allowed struct color in the below example to be on more linked lists then 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);
srparish
+2  A: 

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]);
};
srparish