- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
The first clue that nothing is well is the function signature. Takes no parameters, returns nothing, and yet it's name implies that it does something. That's enough to indicate that global variables and side-effects up the wazoo will be your next step on your journey to ...
Admin
I still don't understand why macros exist rather than just defining a function. They're a subtly different language feature that's easy to mess up. What do they add over normal functions that makes it worth the extra complexity?
I'm talking about C/C++ macros specifically here. I know languages like lisp use the term for something related but more integrated into the language
Admin
#define WTF true
Admin
Mostly history. Nearly everything cpp is used for now could be replaced by some other language or compiler feature, but when C was designed, a single relatively simple tool that does all of them jankily and could in principle be bodged to other uses, was deemed preferable to the complexity/performance impact of those other features, especially on 1970s hardware.
This particular use of macros smells of using them to emulate inlining, which modern compilers do very aggressively, provided the function definition is available (which means link-time optimisation or sticking it in a header).
Admin
static inline
functions do very well at being inlined in modern C, at least with any compiler you're actually likely to use. You can even have multiple definitions of them in different files without things breaking; you get similar benefits to what you have at the saner end of templating in C++. There are things you can do with macros which those functions can't do, but it's often a good idea to make as much as possible of the more complicated parts be functions.Admin
Also, GISs are high WTF territory. I didn't know anyone would be mad enough to interface to them in C.
Admin
When you reach these words, you can confidently stop reading the article, knowing that no greater WTF is possible.
Admin
Why macros and not functions? If you're a gray beard, functions used to have two big problems.
Firstly, functions polluted the global namespace. For small programs, that's not a problem. For a big program, it's a big problem. Worse, C didn't always support long function names (see IEFBR14 for a similar problem with function name :-) ).
Secondly, functions were always slow -- this is before inlining functions was a thing,
And lastly: macros can change the state of function-local variables, and functions can't. done well, this is a help; done poorly, it's leads to a mess of code.
Addendum 2023-11-16 11:25: Edit: I wrote "pollute the global namespace" -- is more nuanced than that, but it's close enough for rock-and-roll
Admin
And more to the point, it's very often done somewhere in-between, but the acceleration from "this is a help" towards "leads to a mess of code" is extremely fast.
Admin
In the early days of C, the compiler was a lot more primitive than modern compilers and the language itself lacked features.
For example:
There was no way to define a constant so preprocessor macros was used instead.
As others have said, there was no function inlining so for small functions, using a macro instead represented an optimisation
All arguments are call by value. A function couldn't change something passed to it in such a way that the change was visible to the caller except by passing a pointer and dereferencing it inside the callee. Macros let you do that without the added syntax and overhead.
You could also use macros to hide messy implementation details e.g. system calls or non portable stuff without the overhead of a function call
If you didn't like C, you could use macros to pretend you weren't programming in C. OK this one is stretching the point a bit. Try tracking down a copy of the original source for the Bourne shell to see what I mean. If you do find a copy, I warn you, you're going to need some eyeball bleach as well. It makes most of the WTFs you read here seem somewhat petty.
Admin
I agree in the overhead being a potential problem in older compilers and hardware. But the added syntax I consider, if anything, an advantage...
Working with Fortran, I despise "pass by (mutable) reference", when there is nothing on the call-site marking that fact.
Addendum 2023-11-16 15:17: I forgot that seeing a
&
in C doesn't tell you if it is a pointer-to-const or a pointer-to-mutable, so the extra syntax actually doesn't add value in that regard...Admin
Macros are still used today to populate arrays of structures.
Let's say you have a structure that has to hold a lot of data at runtime, but only needs to hold a bit of data at compile time - perhaps it's a list of global variables, or maybe it's a mapping of names to variable and string types.
E.g., you want to define something that maps a variable to a string, so you could say match it. You could define a structure to have both like { { variable1, "variable1" }, { variable2, "variable2" }, ... }
but that gets tedious and you may end up with a desync between the variable and the name. A clever macro can easily be able to do that AND avoid a possibility of the name and variable desync:
#define PARAM(name) { name, #name } which gets you
{ PARAM(variable1), PARAM(variable2) }
Windows uses a lot of it to hide the fact it likes to overload variables - return values often have a return code (lower 16 bits) plus an origin and domain code (upper 16 bites). Macros are used to extract those values in a readable way rather than random looking shifts and binary operations.
Admin
Without C macros, we would not have had MFC and ATL.
Ok I guess I'm not making a positive point for them here.
Admin
Hey, those were great for their time.
Admin
I remember macros also being used for debug statements, so that if some flag wasn't enabled then the statements were not compiled into the code at all.
Admin
All input to interpolate is global. So you just pass param and el as parameters to el and you are done except for the error handling. And since it is static, you have the source file where it is called.
Admin
Eyeball bleach indeed. loop/pool made me chuckle though. Maybe this handbasket has descended further than we thought.
Anyone for some C horror can find it here: http://web.archive.org/web/20090129181202/http://minnie.tuhs.org/UnixTree/V7/usr/src/cmd/sh/
mac.h is the source of this inferno http://web.archive.org/web/20090125153700/http://minnie.tuhs.org/UnixTree/V7/usr/src/cmd/sh/mac.h.html
Admin
Macros can still be useful for generating boilerplate code that varies in ways that can't be encapsulated into a function e.g. defining a family of forwarding functions. The only viable alternative for that is some sort of templating processing like T4.