2020-08-27

Pseudo C++ using cpp (the RevK macro)

I am not sure if this is evil, or genius, or both. Either way I take full credit.

Mainly for a library where we want to add extra optional options in the future, so want almost C++ style optional and tagged arguments to a function, but in normal C (because C++ is just evil all by itself).


Not quite as flexible as C++, as no defaults for missing arguments, but you can often live with that knowing they are zero or NULL.

Unless someone can cite a prior art - please call this the RevK macro.

P.S. I have updated my string decimal library to use this, and it is way neater!

Some explanation...

Normally a function call in C has a fixed set of arguments. Well, not quite, some can have variable arguments at the end, like printf(...) but that is handled in a special way and you have to know (usually from a format string) how many arguments and which type.

However, in some languages, like C++, you can have optional arguments which are pre-defined types and names, but you can stop early in the list. In C++ you can say what default these missing arguments have. You also have the option to leave some arguments our and "tag" some others.

So, the idea you can call myfunc("hello",flag2:1) is setting the first argument (s), and the third (flag2) and not specifying the middle one (flag1) which ends up zeroed. I can't set defaults but can expect unspecified to be zeroed.

Now, normally, if I had some function you call as func(a,b,c) and I want some extra option later on, I would have to either change to func(a,b,c,d) everywhere it is used in every program, even if people specify d as 0 or NULL,  or make a new separate function that takes the extra argument as an alternative, e.g. func2(a,b,c,d).

With this trick I am able to add this extra argument which is optional, knowing that if the extra argument is not specified it has a known value of 0/NULL.

The way the trick works is by using the standard C pre-processor which does text substitution, and expanding the full list of arguments (...) in the macro (as __VA_ARGS__) within a structure initialisation. Unlike function arguments, C has a syntax to initialise a structure which allows you to omit arguments and tag arguments. I am using that syntax in the function, so myfunc("hello",flag2:1) becomes a structure initialiser {"hello",flag2:1} and this structure is passed to the function.

Of course I could just used C++, but that comes with a lot of other baggage, and not something I am that keen on. It has its merits and works well for some applications.

8 comments:

  1. Nice!

    Side note: slightly nonportable: the no-argument variant (the first call to myfunc()) is not valid C99 nor C11, but *is* a GCC extension widely supported by other compilers. The portable (but ever so ugly and weird) call there is myfunc("hello",);

    ReplyDelete
    Replies
    1. Surely a structure initialised as {} is valid even in C99? and hence the () version would work after cpp expansion. TBH I use too many gcc extras already that it is not an issue, but interesting.

      Delete
    2. ... oh yeah, it's inside an initializer, so yes, that would work, and also I shouldn't post when exhausted (i.e., at all, right now).

      Delete
  2. For the non-C programmers like me, would you mind explaining step by step what's going on here and why it's worthy of being RevKified?

    ReplyDelete
  3. AFAIK, that colon syntax is a non-standard (and obsolete) GCC extension.

    The standardised form being ".fieldname".

    I'd not be surprised if the colon form is removed in some future version of GCC.

    https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Designated-Inits.html

    Yes, others have used a macro around such struct initialisers, but in the standard form.

    ReplyDelete
    Replies
    1. Interesting. The main trick is using it in a macro to make it seem like function arguments, and the .x= syntax is not quite as nice for that but sill works as a way to make variable argument and tagged functions in C.

      Delete
  4. If you are challenging C to this level and need the kind of power that C++ has bu i thought its ugliness and madness, then definitely take a look at D - google "DLang". (I’ve mentioned this before, so apologies.) D has compile-time function evaluation and a ultra-powerful templates with a sane syntax. See: https://dlang.org/ and http://ddili.org/ders/d.en/

    ReplyDelete

Comments are moderated purely to filter out obvious spam, but it means they may not show immediately.

Fencing

Bit of fun... We usually put up some Christmas lights on the house - some fairy lights on the metal fencing at the front, but a pain as mean...