#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
The above line is take from Unreal 4, and I know I could ask it over on the unreal forums, but I think this is a general C++ question that warrants being asked here.
I understand the first line defines a macro, however I am not well versed in preprocessor shenanigans in C++ and so I'm lost over there. Logic tells me the backslash means the declaration continues onto the next line.
FThreadSafeStaticStat looks a bit like a template, but there's #'s going on in there and a syntax I've never seen before in C++
Could someone tell me what this means? I understand that you may not have access to Unreal 4, but it's just the syntax I don't understand.
## is the preprocessor operator for concatenation.
So if you use
DEFINE_STAT(foo)
anywhere in the code, it gets replaced with
struct FThreadSafeStaticStat<FStat_foo> StatPtr_foo;
before your code is compiled.
Here is another example from a blog post of mine to explain this further.
#include <stdio.h>
#define decode(s,t,u,m,p,e,d) m ## s ## u ## t
#define begin decode(a,n,i,m,a,t,e)
int begin()
{
printf("Stumped?\n");
}
This program would compile and execute successfully, and produce the following output:
Stumped?
When the preprocessor is invoked on this code,
begin is replaced with decode(a,n,i,m,a,t,e)
decode(a,n,i,m,a,t,e) is replaced with m ## a ## i ## n
m ## a ## i ## n is replaced with main
Thus effectively, begin() is replaced with main().
TLDR; ## is for concatenation and # is for stringification (from cppreference).
The ## concatenates successive identifiers and it is useful when you want to pass a function as a parameter. Here is an example where foo accepts a function argument as its 1st argument and the operators a and b as the 2nd and 3rd arguments:
#include <stdio.h>
enum {my_sum=1, my_minus=2};
#define foo(which, a, b) which##x(a, b)
#define my_sumx(a, b) (a+b)
#define my_minusx(a, b) (a-b)
int main(int argc, char **argv) {
int a = 2;
int b = 3;
printf("%d+%d=%d\n", a, b, foo(my_sum, a, b)); // 2+3=5
printf("%d-%d=%d\n", a, b, foo(my_minus, a, b)); // 2-3=-1
return 0;
}
The # concatenates the parameter and encloses the output in quotes. The example is:
#include <stdio.h>
#define bar(...) puts(#__VA_ARGS__)
int main(int argc, char **argv) {
bar(1, "x", int); // 1, "x", int
return 0;
}
Related
Is it possible to prefix each element of variadic parameters with something else?
#define INPUTS(...) ???
Function(INPUTS(a, b, c))
should become
Function(IN a, IN b, IN c)
Take a look at Boost.Preprocessor.
While daunting, it can be used to do all kinds of weird things, like exactly this:
#include <boost/preprocessor.hpp>
#define MAKE_IN_ARG(r,_,arg) (IN arg)
#define ARGS(...) \
BOOST_PP_SEQ_TO_TUPLE( \
BOOST_PP_SEQ_FOR_EACH(MAKE_IN_ARG,, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
void f ARGS( int a, float b, char c )
{
//...
}
Produces:
void f (IN int a, IN float b, IN char c )
{
}
That said...
You are making a mistake. Don’t do this. Just type out the IN in front of every input argument when you write the function header. Your life will be significantly easier.
I would like to ask why this code prints out 2 instead of 0. Doesn't #define "assign" values to the names of the macros and calculate also the result? How does it give this answer?
#include <iostream>
using namespace std;
#define A 0
#define B A+1
#define C 1-B
int main() {
cout << C<<endl;
return 0;
}
Macros are direct text replacements That means
#define C 1-B
becomes
1-A+1
and then A gets expanded so we have
1-0+1
which is 2. If you want 0 then stop using macros and instead use constant variables
const int A = 0;
const int B = A + 1;
const int C = 1 - B;
And now C is 0.
The preprocessor expands the C macro to 1-B, which expands to 1-A+1 which expands to 1-0+1 which equals 2. Don't think of it in terms of sequential assignment, but you can get the desired behavior by adding parenthesis around the macro definitions. Then the C macro would expand to (1-B), then (1-(A+1)) then (1-((0)+1)) which equals 0.
Edit:
As an example, the code snip below prints 42, even though BAR is "assigned" to FOO when FOO equals 17. This is because the expansion is deferred until it's actually used. On the cout line, BAR is still equal to FOO, but at that point, FOO is now 42, not 17. Note that it's bad practice to redefine a macro without first #undefining it.
#define FOO 17
#define BAR FOO
#define FOO 42
cout << BAR << endl;
Because C expands to 1-0+1
Preprocessor defines simply replace text and don't care about operator precedence or calculation rules.
A macro with a ## will concatenate the two elements together, for example if you use #define sptember oct ## ober you will obtain october.
So my problem is:
I have a macro like this #define getRegByPin(pin) set ## pin than I have from 1 to 19 some defines like this: #define set0 xxx and #define set1 xxx, etc.
But when I call my macro in code
int p = getPinNo(pin); st(getRegByPin(p), p, to); it replaces getRegByPin(p) with setp instead of set0 or set13 or etc.
What can i do?
Thx for help! You are awesome! :)
The C preprocessor (and C++ has just inherited it), just does textual substitution. It knows nothing of variables. So given
#define getRegByPin(pin) set ## pin
const int p = 5;
getRegByPin(p); // Will expand to setp, not set5
From the syntax, I guess that set0 to set13 are constants. Do they have values you can calculate? For example:
auto getRegByPin(int pin) { return set0+pin; } // or (set0 << pin)
If not, you are going to need a constant array which you can index:
auto getRegByPin(int pin) {
static const setType_t pins[16] = { set0, set1, set2 ... set15};
return pins[pin];
}
If they are not constants, but functions, your array will need to be an array of function pointers.
Prefer to use functions than the preprocessor.
I am using the X macro pattern to keep a bunch of arrays/items in sync, and I want to create an argument list from it, however I can't work out a way to get a well formed list. Here's what I mean:
#define MY_DATA \
X(var_one, e_one, 1) \
X(var_two, e_two, 2) \
X(var_three, e_three, 3) \
#define X(a,b,c) b,
enum MyNumbers {
MY_DATA
};
#undef X
#define X(a,b,c) c,
int MyValues[] = {
MY_DATA
};
#undef X
void my_func(int a, int b, int c) {} // example do-nothing proc
void main(void)
{
int var_one = MyValues[e_one];
int var_two = MyValues[e_two];
int var_three = MyValues[e_three];
#define X(a,b,c) a,
my_func(MY_DATA); // this fails because of the trailing comma
#undef X
}
Macros are not really my forte, so I can't think of a way of getting rid of the final comma in the function call. Can anyone think of a way to stop it?
Look at the Boost Preprocessor library for “preprocessor metaprogramming tools including repetition and recursion.”
Even if you don't use their complete package, the chapter I linked to explains some techniques, specifically including iteration to build data structures and statements.
Here's an idea: write
my_func(MY_DATA 0);
and declare my_func to take an extra (ignored) argument.
void my_func(int a, int b, int c, int)
I use a variant of this pattern frequently. However, it is normally used to define mappings between data. Along the lines of this:
MESSAGE(10, "Some error message"),
MESSAGE(11, "Som other error message"),
What des not make sense in your approach is that typically these constructs are used for large numbers of entries (100s, 1000s). You normally do not want that many arguments to a function.
If you really want to follow the approach, you could add another MACRO
#define MY_DATA \
X(var_one, e_one, 1) COMMA \
X(var_two, e_two, 2) COMMA \
X(var_three, e_three, 3) \
and define comma as needed when you define X. (Or you could just put the comma in directly).
Here is an option:
void my_func(int a, int b, int c, int dummy) {}
// ...
my_func(MY_DATA 0);
If you can't change my_func then make a thunk (i.e. an intermediate function that calls my_func)
A second option would be to include the comma in the MY_DATA macro instead of in X:
#define MY_DATA \
X(var_one, e_one, 1), \
X(var_two, e_two, 2), \
X(var_three, e_three, 3)
This has been bugging me for some time, I came across this while solving some objective type questions in C.
#define SWAP(a,b,c) c t;t=a;a=b;b=t;
int main() {
int x=10,y=20;
SWAP(x,y,int);
}
The code gives the correct answer:
Working code
In C are we supposed to pass just a data type as an argument.This supposedly works here but I want to know how.Also two more questions related to this:
If I want to swap using pointers, will it work
Will this work if SWAP is defined as a function instead of a macro.
Macros are pre-processed before compilation and you can virtually write anything in macros that would be replaced. In function arguments, you can not pass data types as arguments.
Side note:
#define SWAP(a,b,c) do { c t;t=a;a=b;b=t; } while(0)
is a safer macro implementation than the one mentioned by you. Moreover name t is quite common. If either of the argument name is t, this won't work as expected, so better choose some rare name. Capital letters are usually preferred in macro definition.
for ex: #define SWAP(a,b,c) do { c MACRO_TEMP_;MACRO_TEMP_=a;a=b;b=MACRO_TEMP_; } while(0)
SWAP(x,y,int); Becomes c t;t=a;a=b;b=t; where all occurances of c are replaced with int, a with x and b with y. Resulting in: ìnt t; t = x; x = y; y = t;
To understand the macros better, you can see the pre-processed output of your code. Output on my computer:
$ cat q26727935.c
#define SWAP(a,b,c) c t;t=a;a=b;b=t;
int main() {
int x=10,y=20;
SWAP(x,y,int);
}
$ gcc -E q26727935.c
# 1 "q26727935.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "q26727935.c"
int main() {
int x=10,y=20;
int t;t=x;x=y;y=t;;
}
$
Macro is replacement at pre-processor stage, so swap will work even with pointers, although this is superfluous.
In function you can not pass data type as arguments, so it won't work.
Yes.
No.
First of all, you have to know that when you are using macros, the argument will be replaced as they are. So, if you call SWAP(a, b, int*), it will be replace with
int* t;t=a;a=b;b=t;
and then the code will be compiled.
But when you're using functions, that won't happen and you're unable to pass data type as an argument to a function.