I want to have functions which can have optional arguments. Of course this cannot be done with C, but it is possible with some macro magic:
#define _macroWith1Arg(_0, _1, macroName, ...) _ ## macroName
#define _macroWith2Args(_0, _1, _2, macroName, ...) _ ## macroName
#define _macroWith3Args(_0, _1, _2, _3, macroName, ...) _ ## macroName
#define macroWith1Arg(macroName, ...) _macroWith1Arg(_0, __VA_ARGS__, macroName ## _1, macroName ## _0)(__VA_ARGS__)
#define macroWith2Args(macroName, ...) _macroWith2Args(_0, __VA_ARGS__, macroName ## _2, macroName ## _1, macroName ## _0)(__VA_ARGS__)
#define macroWith3Args(macroName, ...) _macroWith3Args(_0, __VA_ARGS__, macroName ## _3, macroName ## _2, macroName ## _1, macroName ## _0)(__VA_ARGS__)
#define _sum_1(_1) (_1)
#define _sum_2(_1, _2) (_1) + (_2)
#define sum(...) macroWith2Args(sum, __VA_ARGS__)
fprintf(stderr, "%d ", sum(1)); // Prints 1
fprintf(stderr, "%d ", sum(1, 2)); // Prints 3
I like the way it looks: it looks like a normal function with optional arguments. But the drawback of this is you can't have a function pointer to a macro like sum. So I heard you should capitalize the name to mark it explicit as a macro (like "SUM") to avoid confusion.
Now I my question is: is this naming convention really necessary, I mean standard C does it with errno for example (at least on my platform)? I think most IDEs can identify macros and highlight them as such. I would really like to hear your opinion on this.
EDIT:
I found a way to achieve that you can take a function pointer:
int my_sum(int, int);
#define _sum_1(_1) my_sum(_1, 0)
#define _sum_2(_1, _2) my_sum(_1, _2)
#define sum(...) macroWith2Args(sum, __VA_ARGS__)
int (*sum)(int, int) = my_sum;
// Use it as a "function":
fprintf(stderr, "%d ", sum(1, 2)); // Prints 3
// Take a function pointer:
int (*sumptr)(int, int) = sum;
fprintf(stderr, "%d ", sumptr(1, 0)); // Prints 1
In C (the preprocessor is part of it) you can do even more than you are suggesting in your edit: macros and functions can have the same name. Whereas this is rarely done in application code, the C library itself can have that. Here standard functions can be implemeted as macros, but a symbol with the same name must also be provided.
So the standard itself doesn't stick to the rule that macro names should be all caps.
I think that if you are careful in your implementation such that
calling the macro with a full set of parameters just is the identity in the preprocessor phase
a valid function declaration is provided with the same name
then there should be no problem in using a lowercase identifier.
By that you ensure that
repeating the prototype for your function is still a valid operation
taking a function pointer can be done without problems
and in all your implementation is behaving as if your macro where a function.
BTW, the code that you posted is not standard conforming. Indentifiers starting with an underscore are reserved in file scope. This is not a convention but imperative.
Naming conventions generally aren't necessary. They exist to communicate information to other programmers (including yourself a few weeks/months in the future). When another programmer sees
sum(a, b, c, d);
They will immediately think that it's a normal function that takes 4 parameters. However, if they see
SUM(a, b, c, d);
Then they will know it's a macro (assuming they are familiar with C naming conventions). After all, you're not always going to be viewing files in an IDE that knows about what macros and functions you've defined. People will see your code in diff tools and in text editors. They will generally expect macros to be in all caps and symbols that aren't in all caps to be things other than macros.
convention works less in C. since C has fewer tools and compiler does less work, programmers have to be flexible to achieve some purpose. say the convention of macros is uppercase + underscore, but if you want to make people think some macros are functions, it's better for you to not follow this convention. in fact, some libraries fake a field in struct by not following this convention.
you mentioned errno. it's a good example. it's essentially a macro(glibc), returning a left value, so you can write errno = 0;. so in this way, library provider made you think errno was a global variable(this used to be what i thought it was too.), which is not. C programmers tend to be flexible and play some reasonable tricks. it's not the same as Java or C# this kind of enterprise oriented languages, which require programmers to strictly follow conventions.
// notice that the handling of a variable argument list
// is simple, built into C, and does not require a bunch of
// home grown macros.
// this function will take the number of values to average
// followed by all of the numbers to average
double average ( int num, ... )
{
va_list arguments; // A place to store the list of arguments
double sum = 0;
va_start ( arguments, num ); // Initializing arguments to store all values after num
for ( int x = 0; x < num; x++ ) // Loop until all numbers are added
{
sum += va_arg ( arguments, double ); // Adds the next value in argument list to sum.
}
va_end ( arguments ); // Cleans up the list
return sum / num; // Returns the average
}
Related
I would like to pass 2 arguments to a macro using another macro:
#define A_AND_B 5,1
#define ADD(a, b) a + b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
I would hope that expands to
int result = 5 + 1;
and I get 6. Instead I get
Error 'ADD' undeclared (first use in this function)
Error macro "ADD" requires 2 arguments, but only 1 given
Is there a way around this?
As is often the case, you need an extra level of (macro) indirection:
#define A_AND_B 5,1
#define ADD(...) ADD_(__VA_ARGS__)
#define ADD_(a, b) a + b
int add_them(void)
{
int result = ADD(A_AND_B);
return result ;
}
ADD is defined as variadic so that it will work as either ADD(A_AND_B) or ADD(A, B).
This works because __VA_ARGS__ in the replacement body of ADD is replaced with the actual arguments before the replacement body is scanned for macros.
Per C 2018 6.10.3.1, a compiler first identifies the arguments for a function-like macro and then performs macro replacement on the arguments, followed by macro replacement for the function-like macro. This means that, in ADD(A_AND_B), the argument is identified as A_AND_B before it is replaced with 5,1. As the macro invocation has only this single argument and the macro is defined to have two parameters, an error is diagnosed.
Given your definition of ADD, there is no way to change this behavior in a compiler that conforms to the C standard.
You can instead use another macro to expand the arguments and apply the desired macro:
#define Apply(Macro, Arguments) Macro(Arguments)
then int result = Apply(ADD, A_AND_B); will work. That will identify ADD and A_AND_B as arguments to Apply. Then it will expand those, producing an unchanged ADD and 5,1. Then the macro replacement for Apply produces ADD(5,1). Then this is again processed for macro replacement, which replaces ADD(5,1) in the ordinary way.
Note that good practice is usually to define ADD as #define ADD(a, b) ((a) + (b)) to avoid unexpected interactions with other operators neighboring the use of the macro.
Need max/min with unknown number of arguments, like :
#define MAX_N(first, second, remain...) MAX_N(((first)>(second)?(first):(second)), ##remain)
In my opinion, this will not keep expanding infinitely and should be accepted by compiler?
Unfortunately, I have to use pure C rather than C++.
C 2018 6.10.3.4 2 says, about rescanning the result of macro replacement for further macros:
If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced…
Therefore, recursive macros are not possible, not even just for two levels, let alone indefinitely many.
It is possible to cause macros to be expanded multiple times by using other macros to expand them. As a simple example, after #define X Y Y, X will be replaced by two occurrences of Y, each of which, if it is a defined macro, will be replaced—but separately, not recursively. This can be exploited to create macros that cause sone finitely limited number of expansions, but indefinitely many expansions are not possible.
Why do you need a recursive macro? you can write a variadic min/max function like this:
#include <stdio.h>
#include <stdarg.h>
// credit for NUMARGS: https://stackoverflow.com/a/2124433/2889478
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define MAX(...) (max_variadic(NUMARGS(__VA_ARGS__), __VA_ARGS__))
int max_variadic(int narg, ...)
{
va_list args;
int pos = 0, max_val = 0;
va_start(args, narg);
while (narg--) {
int i = va_arg(args, int);
max_val = !pos ? i : i > max_val ? i : max_val;
pos++;
}
va_end(args);
return max_val;
}
int main(void)
{
int mx = MAX(4, 6, -1, 9, 2);
printf("%d", mx);
}
There were several questions here regarding variadic macros in C. These include:
How to make a variadic macro (variable number of arguments) which explains the basics, e.g., passing a variable number of arguments to functions such as printf
Is it possible to iterate over arguments in variadic macros?, which explains how to iteratively apply a macro to each of the arguments of the variadic macro.
https://github.com/swansontec/map-macro which explains how to do so on pairs
My question is related to the iteration technique. I am interested in a macro with this generalized semantics.
ITERATE(Before, Action, Between, After, Empty, ...)
that will place Before prior to all expansions, apply Action to each argument, place Between between every two consecutive applications, and will finally place the expansion of After. Moreover, if the number of argument With such a macro, it should be possible to write
// Loop elements
#define A(x) (x)
#define Befor (
#define After )
#define Between ||
#define Empty 1
// Define an OR macro
#define OR(...) ITERATE(Before, A, Between, Empty, __VA_ARGS__)
// Use it
OR() // Expands to 1
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
The purpose of course is not to write an OR function. A generalized functionality could be for more intricate applications. E.g., a macro for defining classes and functions, something to print the trace, etc.
I never liked the recursive REPEAT() macro idiom - it generates horrible hour long read error messages that are.. recursive, so you don't know where the error is and it's also hard to grasp how the OBSTRUCT(REPEAT_INDIRECT) () stuff works. Overall, overloading the macro on number of arguments and using an external tool (shell script or m4 preprocessor) to generate C source code is waay easier, easier to read, maintain and fix and also you can expand the macros on the tools side removing the burden of recursive expansion on C side. With that in mind, your ITERATE can be generated with existing preprocessor libraries, P99_FOR or BOOST_FOREACH comes to mind.
Also, typing shift all the time is strange - I prefer snake case. Here's a reduced example without Before and After macros with overloading the macro on number of arguments:
#define _in_ITERATE_0(f,b,e) e()
#define _in_ITERATE_1(f,b,e,_1) f(_1)
#define _in_ITERATE_2(f,b,e,_1,...) f(_1)b()_in_ITERATE_1(f,b,e,__VA_ARGS__)
#define _in_ITERATE_3(f,b,e,_1,...) f(_1)b()_in_ITERATE_2(f,b,e,__VA_ARGS__)
// or you could expand it instead of reusing previous one with same result:
#define _in_ITERATE_4(f,b,e,_1,_2,_3,_4) f(_1)b()f(_2)b()f(_3)b()f(_4)
// etc.... generate
#define _in_ITERATE_N(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) _in_ITERATE_##N
#define ITERATE(func, between, empty, ...) \
_in_ITERATE_N(0,##__VA_ARGS__,9,8,7,6,5,4,3,2,1,0)(func, between, empty, ##__VA_ARGS__)
#define _in_OR_OP(x) (x)
#define _in_OR_EMPTY() 1
#define _in_OR_BETWEEN() ||
#define OR(...) (ITERATE(_in_OR_OP, _in_OR_BETWEEN, _in_OR_EMPTY, ##__VA_ARGS__))
// Use it
OR() // Expands to (1)
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
outputs:
(1)
((a))
((a)||(b))
((a)||(b)||(c))
For more examples on overloading macro on count of arguments see this thread. I am using ## GNU extension to remove the comma before __VA_ARGS__ because I am used to using it - I think __VA_OPT__(,) should be nowadays preferred, I am not sure.
Let's say I have already defined 9 macros from
ABC_1 to ABC_9
If there is another macro XYZ(num) whose objective is to call one of the ABC_{i} based on the value of num, what is a good way to do this? i.e. XYZ(num) should call/return ABC_num.
This is what the concatenation operator ## is for:
#define XYZ(num) ABC_ ## num
Arguments to macros that use concatenation (and are used with the operator) are evaluated differently, however (they aren't evaluated before being used with ##, to allow name-pasting, only in the rescan pass), so if the number is stored in a second macro (or the result of any kind of expansion, rather than a plain literal) you'll need another layer of evaluation:
#define XYZ(num) XYZ_(num)
#define XYZ_(num) ABC_ ## num
In the comments you say that num should be a variable, not a constant. The preprocessor builds compile-time expressions, not dynamic ones, so a macro isn't really going to be very useful here.
If you really wanted XYZ to have a macro definition, you could use something like this:
#define XYZ(num) ((int[]){ \
0, ABC_1, ABC_2, ABC_3, ABC_4, ABC_5, ABC_6, ABC_7, ABC_8, ABC_9 \
}[num])
Assuming ABC_{i} are defined as int values (at any rate they must all be the same type - this applies to any method of dynamically selecting one of them), this selects one with a dynamic num by building a temporary array and selecting from it.
This has no obvious advantages over a completely non-macro solution, though. (Even if you wanted to use macro metaprogramming to generate the list of names, you could still do that in a function or array definition.)
Yes, that's possible, using concatenation. For example:
#define FOO(x, y) BAR ##x(y)
#define BAR1(y) "hello " #y
#define BAR2(y) int y()
#define BAR3(y) return y
FOO(2, main)
{
puts(FOO(1, world));
FOO(3, 0);
}
This becomes:
int main()
{
puts("hello " "world");
return 0;
}
In C, is it possible to concatenate each of the variable arguments in a a variadic macro?
Example:
MY_MACRO(A, B, C) // will yield HDR_A, HDR_B, HDR_C
MY_MACRO(X, Y) // will yield HDR_X, HDR_Y
The normal ## operator has special meaning for variadic macros (avoiding the comma for empty argument list). And concatenation when used with __VA_ARGS__ takes place with the first token only.
Example:
#define MY_MACRO(...) HDR_ ## __VA_ARGS__
MY_MACRO(X, Y) // yields HDR_X, Y
Suggestions?
First, the comma rule you are mentioning is a gcc extension, standard C doesn't have it and most probably will never have it since the feature can be achieved by different means.
What you are looking for is meta programming with macros, which is possible, but you'd need some tricks to achieve that. P99 provides you with tools for that:
#define MY_PREFIX(NAME, X, I) P99_PASTE2(NAME, X)
#define MY_MACRO(...) P99_FOR(HDR_, P99_NARG(__VA_ARGS__), P00_SEQ, MY_PREFIX, __VA_ARGS__)
Here MY_PREFIX describes what has to be done with the individual
items.
P00_SEQ declares how the items should be separated
P99_NARGS just counts the number of arguments