Live data from Hacker News

Recursive macros in C, demystified (once the ugly crying stops)

h4x0r.org

71–80 of 90 posts

Re: Recursive macros in C, demystified (once the ugly crying stops)

#71

Can I use this technique to expand MACRO(a,b,c,…) into something like F(a,b,c…); G(a,b,c…)?

Okay, finally found some time to provide you with a fully annotated example of your original ask here, assuming you wanted to transform the arguments passed to F into IDs, and the arguments passed to G into strings (as seemed to be the case from the rest of the thread).

https://c.godbolt.org/z/6zqx1dsn3

I've fully annotated it, so it might seem like more than it is. About half the macro code is from the original article (the chunk at the top). And I do implement both transforms for you.

Each one I think is only 6 lines of code by itself, despite the rediculous amount of exposition in the comments.

If you have any questions about it, let me know.

Re: Recursive macros in C, demystified (once the ugly crying stops)

#72
post #69
post #68

Earlier quoted context omitted.

If you can give me specifics on how it's not clear, I'd very much want to improve it. Please DM me about it.

Not so much that you are not clear - this is an area that is weird enough that I don't think it is possible to be clear, but you gave me some useful hints. I got some of what I want working. Edit, I started writing and then realized that I need this to work on old gcc that doesn't support these tricks so I have to give up. (I can't wait until this old embedded hardware dies) What I'm trying to do is #define(A, B) sta…

Thanks. Also, per another person in the thread, here are the two annotations he or she was asking for, heavily annotated.

They are both only a couple lines, but it deals with things like the fact that you've got one more argument than you should have commas, and the use of the # and ## operators in these things.

https://c.godbolt.org/z/6zqx1dsn3

Re: Recursive macros in C, demystified (once the ugly crying stops)

#73
post #47
post #28

Earlier quoted context omitted.

Wow, I'm not sure I've ever seen this (or if I did, it was 20 years ago). And I was definitely looking around for this kind of history when I was searching around when writing. Perhaps my google skills have decayed... or google... or both! Thanks very much.

Oh, are you L33 T.?

If my google fu is that bad, it's pretty much impossible to be.

Re: Recursive macros in C, demystified (once the ugly crying stops)

#74
post #70
post #63

Earlier quoted context omitted.

At least you can implement things like vector in C++. I challenge anyone to write the same for C macros. (this is semi-serious - if you get a full generic STL for C that is usable that would prevent a large number of bugs. The implementation can be as bad as you want, so long as the user API is not too difficult. Though note that I'm not a C programmer and so if there are better ways someone else is doing this I'm no…

I wonder how you like my vector: https://godbolt.org/z/97YGrbP9s (note, experimental library, but I see no fundamental issue).

that is amazing... I don't write C so I didn't dig too deep, but kudos for getting anything to work. Now you use need great documentation so we can figure out how to use it and what it supports without digging into the macros themselves. (tests would be good too, but maybe they are there and I didn't see them).

Re: Recursive macros in C, demystified (once the ugly crying stops)

#75
post #69
post #68

Earlier quoted context omitted.

If you can give me specifics on how it's not clear, I'd very much want to improve it. Please DM me about it.

Not so much that you are not clear - this is an area that is weird enough that I don't think it is possible to be clear, but you gave me some useful hints. I got some of what I want working. Edit, I started writing and then realized that I need this to work on old gcc that doesn't support these tricks so I have to give up. (I can't wait until this old embedded hardware dies) What I'm trying to do is #define(A, B) sta…

To be clear, the example I provided for the other person explains the bit you're missing where the names aren't working... if you carefully follow the rules, the # and ## operators don't allow expansion on their arguments, so you have to use a layer of indirection to get them expanded first.

Re: Recursive macros in C, demystified (once the ugly crying stops)

#76
post #60

Related: The Preprocessor Iceberg https://jadlevesque.github.io/PPMP-Iceberg/ There you can find a recursive macro expansion implementation (as a gcc hack) that fits on a slide: #2""3 #define PRAGMA(...) _Pragma(#__VA_ARGS__) #define REVIVE(m) PRAGMA(push_macro(#m))PRAGMA(pop_macro(#m)) #define DEC(n,...) (__VA_ARGS__) #define FX(f,x) REVIVE(FX) f x #define HOW_MANY_ARGS(...) REVIVE(HOW_MANY_ARGS) \ __VA_OPT__(+1 FX(…

You know you're in for a wild ride when the `do { ... } while(0)` hack isn't even on the iceberg.

It is-- if you click in to their full list, you should see it near the top in their "above the water" section, under `#pragma once`. I suspect it was added after the meme image was produced.

But, if it weren't on the iceberg page, it'd make sense. The semantics of `do { ... } while(0)` are in the standard, and the preprocessor has nothing to do with those semantics.

You are, of course, right, that the construct is used all over the place in macros for good reason, though these days every compiler I care about has the same (I believe not in the standard) syntax for statement expressions, which will work in even more contexts.

Re: Recursive macros in C, demystified (once the ugly crying stops)

#77
post #76
post #60

Earlier quoted context omitted.

You know you're in for a wild ride when the `do { ... } while(0)` hack isn't even on the iceberg.

It is-- if you click in to their full list, you should see it near the top in their "above the water" section, under `#pragma once`. I suspect it was added after the meme image was produced. But, if it weren't on the iceberg page, it'd make sense. The semantics of `do { ... } while(0)` are in the standard, and the preprocessor has nothing to do with those semantics. You are, of course, right, that the construct is us…

Ah, I meant that it was in the uppermost, least obscure section, "above the iceberg", not that it wasn't in the picture at all :)

Re: Recursive macros in C, demystified (once the ugly crying stops)

#78
post #50

Earlier quoted context omitted.

They were deliberately leaving their C compiler broken because they considered C++ to be the replacement for C.

C++ uses an identical preprocessor.

That has sometimes been true, but for example C++ didn't have variadic macros, maybe still doesn't, because they were added to C after Microsoft decided to stop following C development. https://stackoverflow.com/a/21515839 goes into details of other differences.

Re: Recursive macros in C, demystified (once the ugly crying stops)

#80
post #72
post #69

Earlier quoted context omitted.

Not so much that you are not clear - this is an area that is weird enough that I don't think it is possible to be clear, but you gave me some useful hints. I got some of what I want working. Edit, I started writing and then realized that I need this to work on old gcc that doesn't support these tricks so I have to give up. (I can't wait until this old embedded hardware dies) What I'm trying to do is #define(A, B) sta…

Thanks. Also, per another person in the thread, here are the two annotations he or she was asking for, heavily annotated. They are both only a couple lines, but it deals with things like the fact that you've got one more argument than you should have commas, and the use of the # and ## operators in these things. https://c.godbolt.org/z/6zqx1dsn3

Thanks. I didn't have enough levels of indirection. Once I add enough levels of indirection it works. Well works on my newer systems, I have to build for an embedded system where I'm stuck on an old compiler that doesn't support these tricks.
Post reply on HN