I'm trying to understand the argument counting in C preprocessing macro and the idea in this answer. We have the following macro (I changed the number of arguments for simplicity):
#define HAS_ARGS(...) HAS_ARGS_(__VA_ARGS__, 1, 1, 0,)
#define HAS_ARGS_(a, b, c, N, ...) N
As far as I understand the purpose of this macro is to check if the given varargs empty. So on empty varargs the macro invokation is replaced with 0 which seems fine. But with a single argument it also turns into 0 which I seems strange.
HAS_ARGS(); //0
HAS_ARGS(123); //also 0
HAS_ARGS(1, 2); //1
LIVE DEMO
I think I understand the reason. In case of empty varargs a is replaced with empty preprocessing token, in case of a single argument vararg a is replaced with the argument yielding the same result.
Is there a way to get 0 returned in case varargs are empty, 1 in case argument number is from 1 to the defined in HAS_ARGS_ macro invokation without using comma-swallowing or other non-conforming tricks. I mean
SOME_MACRO_F() //0
SOME_MACRO_F(234) //1
SOME_MACRO_F(123, 132) //1
//etc
You cannot pass zero arguments to HAS_ARGS(...). ISO C (and C++, at least for the next two years) requires that an ellipsis corresponds to at least one additional argument after the last named one.
If there are no named ones, then the macro needs to be passed at least one argument. In the case of HAS_ARGS() the extra argument is simply an empty token sequence. Zero arguments is simply not possible.
This is exactly the use case in the answer. The target macro expects at least one argument. So we can use a wrapper accepting only an ellipsis for "overload resolution". A better name probably would have been HAS_MORE_THAN_1_ARGS. Because that's what the predicate is meant to tell you. Alas, I favored brevity on that answer.
It seems difficult to compute that at compile-time, but you can do it at run-time by stringifying the arguments and testing if the string is empty.
Tested with gcc:
#include <stdio.h>
#define HAS_ARGS(...) (#__VA_ARGS__[0] != '\0')
int main()
{
printf("%d %d %d %d\n",HAS_ARGS(),HAS_ARGS(10),HAS_ARGS(20,"foo"),HAS_ARGS(10,20));
return 0;
}
this prints:
0 1 1 1
behind the scenes, here's what the pre-processor outputs:
int main()
{
printf("%d %d %d %d\n",(("")[0] != '\0'),(("10")[0] != '\0'),(("20,\"foo\"")[
0] != '\0'),(("10,20")[0] != '\0'));
return 0;
}
Related
For example I have a macro:
#define PRINT(int) printf(#int "%d\n",int)
I kinda know what is the result.
But how come #int repersent the whole thing?
I kinda forget this detail. Can anybody kindely give me a hint?
Thanks!
In this context (applied to a parameter reference in a macro definition), the pound sign means to expand this parameter to the literal text of the argument that was passed to the macro.
In this case, if you call PRINT(5) the macro expansion will be printf("5" "%d\n", 5); which will print 5 5; not very useful; however if you call PRINT(5+5) the macro expansion will be printf("5+5" "%d\n", 5+5); which will print 5+5 10, a little less trivial.
This very example is explained in this tutorial on the C preprocessor (which, incidentally, is the first Google hit for c macro pound sign).
"#" can show the name of a variable, it's better to define the macro as this:
#define PRINT(i) printf(#i " = %d\n", i)
and use it like this:
int i = 5;
PRINT(i);
Result shown:
i = 5
That is a bad choice of name for the macro parameter, but harmless (thanks dreamlax).
Basically if i write like so
PRINT(5);
It will be replaced as
printf("5" "%d\n",5);
or
printf("5 %d\n",5);
It is a process called Stringification, #int is replaced with a string consisting of its content, 5 -> "5"
'#' is called a stringize operator.
Stringize operator puts quotes around the parameter passed and returns a string. It is only used in a marco statements that take the arguments.
#include<stdio.h>
#define stringLiteral(sl) #sl
int main()
{
char StringizeOpreator = 'a';
printf(stringLiteral(StringizeOpreator));
return 0;
}
Here the stringLiteral marco takes the formal argument sl and returns #sl. Actual argument passed is StringizeOpreator variable. The return statement #sl has # operator, that puts quotes around the argument like "StringizeOpreator" and returns a string.
So the output of the above program is the name of the actual parameter 'StringizeOpreator' rather than the value stored in the actual parameter passed.
output :
StringizeOperator
...
exitcode 0
To learn more visit this link:
Stringize Operator
Below I change the value of the function that I call depending on the value of INPUT:
#include <stdio.h>
#define INPUT second
#if INPUT == first
#define FUNCTOCALL(X) first(X)
#elif INPUT == second
#define FUNCTOCALL(X) second(X)
#endif
void first(int x) {
printf("first %d\n", x);
}
void second(int x) {
printf("second %d\n", x);
}
int main() {
FUNCTOCALL(3);
return 0;
}
However, the output is first 3, even if INPUT is equal to second, as above. In fact, the first branch is always entered, regardless of the value of INPUT. I'm completely stumped by this - could someone explain what stupid mistake I'm making?
The c preprocessor only works on integer constant expressions in its conditionals.
If you give it tokens it can't expand (such as first or second where first and second aren't macros)
it'll treat them as 0 and 0 == 0 was true last time I used math. That's why the first branch is always taken.
6.10.1p4:
... After all replacements due to macro expansion and the defined
unary operator have been performed, all remaining identifiers
(including those lexically identical to keywords) are replaced with
the pp-number 0, and then each preprocessing token is converted into a
token. ...
You have no macros first and second defined. Be aware that the pre-processor is not aware of C or C++ function names!* In comparisons and calculations (e. g. #if value or #if 2*X == Y), macros not defined (not defined at all or undefined again) or defined without value evaluate to 0. So, as first and second are not defined, INPUT is defined without value, and the comparison in both #if expressions evaluates to 0 == 0...
However, if you did define the two macros as needed, they would collide with the C function names and the pre-processor would replace these with the macro values as you just defined them, most likely resulting in invalid code (e. g. functions named 1 and 2)...
You might try this instead:
#define INPUT SECOND
#define FIRST 1
#define SECOND 2
#if INPUT == FIRST
#define FUNCTOCALL(X) first(X)
#elif INPUT == SECOND
#define FUNCTOCALL(X) second(X)
#else
# error INPUT not defined
#endif
Note the difference in case, making the macro and the function name differ.
* To be more precise, the pre-processor is not aware of any C or C++ tokens, so it does not know about types like int, double, structs or classes, ... – all it knows is what you make it explicitly aware of with #define, everything else is just text it operates on and, if encountering some known text nodes, replacing them with whatever you defined.
I want to use this macro to put (if 'i' is greater than zero) the symbol '^' and the number I pass (i) to the macro
#define ESP(i) ((i>0) ? ("^"(i)) : "")
I want to call it in this way
printf("%+d%s", n1, ESP(i));
where 'i' is the index of a cycle, but the compilation reports me errors;
how can I modify the code to be right?
Somewhat dirty but should work:
#include <stdio.h>
#define DYNFORMAT(n, i) (i>0) ?"%+d%s%d\n" :"%+d%s%s\n", n, (i>0) ?"^" :"", (i>0) ?i :""
int main(void)
{
int i = 0;
printf(DYNFORMAT(42, i));
i = 1;
printf(DYNFORMAT(42, i));
}
This should print:
+42
+42^1
Disclaimer: I am not sure whether this conforms to the Standard and how to get rid of the warning(s) it gives during compilation.
The clean approach would be to use two calls to printf().
This can be implemented as a macro or a function.
As I love the pre-processor, the macro version here:
#define PRINT_ESP(n, i) \
do { \
if (i = 0) \
printf("%+d", n); \
else \
printf("%+d^%d", n, i); \
} while (0);
Macros operate at compile time, not at run time. They can perform a variety of text-mangling tricks, but they do not evaluate anything. (They can certainly, however, expand to code that evaluates something.) Putting the formatted value of variable i into a string involves evaluating i; no macro can do this.
You could instead expand the scope of the macro to include the whole printf() call:
#define PRINT_ESP(n1, i) do { \
printf(((i > 0) ? "%+d^%d" : "%+d"), n1, i); \
} while (0)
Alternatively, you could use a macro to express just the format selection incorporated into the above macro definition, or you could just put the full printf() call above directly into your code.
All of these variations are based on the fact that arguments in excess of those required by the given format are evaluated prior to the call, but ignored by printf() itself.
You don't need the (i) after the "^". Change your macro to this and it should work #define ESP(i) ((i>0) ? ("^") : ("")). Then in your printf statement if you want to print the value of i after the "^" then have something like this printf("%s%d", ESP(i), i); As far as I know I don't think you can format a string to include an integer inside a macro since that would require calling other functions, so you have to bring the i into the string inside your printf.
For example I have a macro:
#define PRINT(int) printf(#int "%d\n",int)
I kinda know what is the result.
But how come #int repersent the whole thing?
I kinda forget this detail. Can anybody kindely give me a hint?
Thanks!
In this context (applied to a parameter reference in a macro definition), the pound sign means to expand this parameter to the literal text of the argument that was passed to the macro.
In this case, if you call PRINT(5) the macro expansion will be printf("5" "%d\n", 5); which will print 5 5; not very useful; however if you call PRINT(5+5) the macro expansion will be printf("5+5" "%d\n", 5+5); which will print 5+5 10, a little less trivial.
This very example is explained in this tutorial on the C preprocessor (which, incidentally, is the first Google hit for c macro pound sign).
"#" can show the name of a variable, it's better to define the macro as this:
#define PRINT(i) printf(#i " = %d\n", i)
and use it like this:
int i = 5;
PRINT(i);
Result shown:
i = 5
That is a bad choice of name for the macro parameter, but harmless (thanks dreamlax).
Basically if i write like so
PRINT(5);
It will be replaced as
printf("5" "%d\n",5);
or
printf("5 %d\n",5);
It is a process called Stringification, #int is replaced with a string consisting of its content, 5 -> "5"
'#' is called a stringize operator.
Stringize operator puts quotes around the parameter passed and returns a string. It is only used in a marco statements that take the arguments.
#include<stdio.h>
#define stringLiteral(sl) #sl
int main()
{
char StringizeOpreator = 'a';
printf(stringLiteral(StringizeOpreator));
return 0;
}
Here the stringLiteral marco takes the formal argument sl and returns #sl. Actual argument passed is StringizeOpreator variable. The return statement #sl has # operator, that puts quotes around the argument like "StringizeOpreator" and returns a string.
So the output of the above program is the name of the actual parameter 'StringizeOpreator' rather than the value stored in the actual parameter passed.
output :
StringizeOperator
...
exitcode 0
To learn more visit this link:
Stringize Operator
KdPrint(("Enter HelloWDMAddDevice\n"));
What's the reason for doing that?
That is so you can pass an entire argument list to the macro and have it pass it on to a function that takes a variable number of arguments.
I would bet anything that the definition of that macro is:
#if DEBUG /* or something like it */
#define KdPrint(args) (printf args)
#else
#define KdPrint(args) /* empty */
#endif
Or similar to some other function that works just like printf.
If it were defined as printf(args), then you could only pass the single string argument, because an argument to a macro can't contain a comma that isn't inside a nested parenthesis.
It causes everything inside the parens to be treated as a single parameter to the macro. In the example shown, it can allow for varargs types of parameters:
KdPrint(( "My info is %s\n", "my name" ));
As well as
KdPrint(( "fn %s ln %s\n", "my", "name" ));
If the macro in question was not well written using parentheses, it might be necessary because of operator precedence. Take this macro for example:
#define MY_MACRO(a) a * 11
Well, if you did this:
int b = MY_MACRO(1 + 2);
b, instead of being 33 like it should, would actually be replaced with int b = 1 + 2 * 11 which is 23 and not 33. If your macro isn't written like that, though (without parenthesis around the a) then it's unnecessary.
If this is the KdPrint() that you are talking about, then this is because you can use KdPrint() macro with format arguments, and it is not a variable length macro.
For example, you can do:
KdPrint(("The answer is %d\n", 42));
and so on.
For your specific example, I cannot tell you, because I don't know what is XdPrint.
But in a more general case, it is because a macro I just like a search and replace. Suppose you have:
#define MULT(a,b) (a*b)
If you call MULT(1+1, 2+2), it would become 1+1*2+2, and result as 5 instead of 8 as you would expect. Doing MULT((1+1), (2+2)) would gives you the expected result. That is why you need to double the brackets.