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.
Nice!
ReplyDeleteSide 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",);
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... 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).
DeleteFor 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?
ReplyDeleteI'll add an explanation...
DeleteAFAIK, that colon syntax is a non-standard (and obsolete) GCC extension.
ReplyDeleteThe 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.
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.
DeleteIf 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