> If you need macros to hack C to enable some functionality not inherent to the language, you should change the approach or switch to a different language.
I think if you continue to do serious C hacking, you'll find a lot of places where macros are legitimately a good choice.
For example, I've found that macros are very, very useful when it comes to implementing error handling in a robust way. In C, the only real way to detect whether a function has failed is to return an error code. The caller then has to test for the error code and take the appropriate action if there was an error. I'm working on a side project now that was doing a LOT of this because it does a lot of IO and memory allocation (and basically any operation you do on a file or any call to `malloc` or a function that calls `malloc` can spontaneously fail in C). So my source code, after a while, ended up looking more or less like this:
if ((f = open_file()) == NULL)
return ERROR_CODE;
if ((s = allocate_string()) == NULL)
return ERROR_CODE;
if (write_string_to_file(s, f)
... and so on, and so forth. It got to the point where basically all of the function calls I did needed to be manually checked for an error, which made all of my code really messy and hard to read. The only real way to refactor these checks in pure C without sacrificing robustness is to use a macro:
#define MY_ASSERT(c) do { if (!(c)) return ERROR_CODE; } while (0)
MY_ASSERT((f = open_file()) != NULL);
MY_ASSERT((s = allocate_string()) != NULL);
MY_ASSERT(write_string_to_file(s, f) >= 0);
This has the same effect as the code above, without sacrificing comprehensibility or readability.
> Also macros are usually used to "speed up" the code. You should never optimize before finding the real bottleneck in your code. And thus always use functions instead of macros.
I think a lot of people on HN and /r/programming fail to understand why premature optimization is a bad thing. A lot of programmers hide behind the "premature optimization is the root of all evil" thing to justify their pre-existing biases or their inefficient code. The point is that you shouldn't spend a great deal of time optimizing functions or algorithms unless optimizing those functions or algorithms will be productive. It's wasteful to spend a bunch of time optimizing your IO operations, for example, if 95% of the time is being spent in the database. The macro-vs-function debate has nothing to do with that. Writing a macro definition takes no more effort than writing a function definition, so you shouldn't be opposed to writing
#define SOME_OPERATION(x) (((x) * 100) / 3 + 500)
rather than
int some_operation(int x) { return (x * 100) / 3 + 500; }
That isn't premature optimization, you're just guaranteeing that the compiler won't introduce the overhead of a function call.