C preprocessor tricks, tips, and idioms (2015)
github.com
github.com
The result was surprisingly pleasing. The code looked much nicer without all the #'s breaking up the indentation, and it made C look like a more modern language :-)
Hey guess what REQUEST and REQUEST_FIXED_SIZE do here: https://gitlab.freedesktop.org/xorg/xserver/blob/master/dix/... Did you guess "declares a new variable called 'stuff'" and "returns early", respectively?
Do you think dixAllocateObjectWithPrivates is a function here? https://gitlab.freedesktop.org/xorg/xserver/blob/master/dix/... Haha, think again! Macro.
Guess what fbGetPixmapBitsData does here: https://gitlab.freedesktop.org/xorg/xserver/blob/master/fb/f... Did you guess assign values to the latter 3 arguments, two of which aren't even passed by reference??
I'm picking on the xserver because it's my most memorable encounter with bad macros, but agh. Agh!
ProcQueryExtension(ClientPtr client)
{
xQueryExtensionReply reply;
int i;
REQUEST(xQueryExtensionReq);
REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
reply = (xQueryExtensionReply) {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.major_opcode = 0
};
What's wrong with: ProcQueryExtension(ClientPtr client)
{
xQueryExtensionReply reply = {
.type = X_Reply,
.sequenceNumber = client->sequence,
.length = 0,
.major_opcode = 0
};
int i;
REQUEST(xQueryExtensionReq);
REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
Can't we define and initialize a structure any more without some damned compound literals?> Did you guess assign values to the latter 3 arguments
In C++, functions do that.
void assign(int &target, int val) { target = val; }
assign(x, 42);GP means 'they do that unexpectedly.' In your C++ code, your function doesn't just up and decide to make changes to the parameters; `target` is a reference and therefore the caller should expect it to be modified. In GP's case, he's presumably complaining that the macro definition for `fbGetPixmapBitsData` gives no indication that the last three arguments will have their addresses taken to be passed elsewhere.
Sorry, you don't hold water. A C++ function can be edited from a pure function to one with non-const, mutated ref parameter, and some (perhaps all) uses of that function in the program will still compile. That counts as "just up and decide to make changes to the parameters".
You have to read the definition to see what is going on, just like with a macro.
> macro definition for `fbGetPixmapBitsData` gives no indication that the last three arguments will have their addresses taken to be passed elsewhere.
If there is no indication, then it's not that macro itself that is arranging the mutation syntax. It must be expanding into something that looks innocent. E.g. we can have a macro over my C++ assign function above:
#define asn(x, y) assign(x, y)
Sure, the macro definition doesn't give a clue because it expands to something that looks like another function or macro call, which we then have to understand. The C++ function is the culprit that is mutating x, not the macro.It's true that with macros, we can build up a labyrinth of expansions where such a thing can hide more easily; whereas if we use nothing but C++ functions, the one we are calling has to steal that address, not any of its delegates.