If a=1, b=2, c=3... I would like to write a macro which concatenates them like this 123. But when I try this:
#include<stdio.h>
#define cat(a,b,c) a##b##c
int main()
{
开发者_StackOverflowint a=1,b=2,c=3,d;
d=cat(1,2,3); //Works
d=cat(a,b,c); // Returns an error...How to make this work?
return 0;
}
You can't -- the preprocessor has no idea about variables and what values you're going to assign to them when the program runs at some arbitrary time after the preprocessor has finished executing.
hash-define macros are pre-compile time and are preprocessed before compilation. The preprocessor will not have access to variable values. d=cat(a,b,c)
will get converted to d=abc
by the preprocessor.
You would need to use itoa
or something similar and concatenate the resulting strings and then atoi back.
Or just do some arithmetic to figure out the result.
Preprocessor stringifying can't work on variables, it has to take a literal and convert it to a string during processing; the preprocessor deosn't know what a
, b
, and c
equals in your cat()
call. You would need to write a macro that actually uses C++ to do the combining. For example:
#define cat(a, b, c, d) \
do { \
std::stringstream ss; \
ss << a << b << c; \
ss >> d; \
} while(0)
(the do/while(0)
is a common hack to let you add a semi-colon after the cat
call safely)
You won't be able to use a "return value" from this, but you can do:
int a = 1, b = 2, c = 3, d;
cat(a, b, c, d);
// d == 123 now
This might be a starting point:
#include <stdio.h>
#define cat(x,a,b,c) snprintf(x, sizeof(x), "%d%d%d", a, b, c)
main(int argc, char *argv[])
{
char s[20];
cat(s, 4,5,6);
printf("%s\n", s);
}
if it it isnt important that this is done at compile time, you can use something like this:
#include <math.h>
unsigned intcat(unsigned a, unsigned b, unsigned c)
{
unsigned dlogc = 1 + (unsigned)(log(c)/log(10));
unsigned dlogb = 1 + (unsigned)(log(b)/log(10));
return (unsigned)(c + pow(10,dlogc) * b + pow(10,dlogb+dlogc) * a);
}
i dont know if there is anything in the boost libraries to do such math at compile time using TMP.
It is possible for preprocessor defined integers.
The preprocessor needs a call to another function to expand.
You do it as follows:
#define I_BASE_CONCAT(x,y) x ## y
#define I_CONCAT(x,y) I_BASE_CONCAT(x,y)
There it is. Now if you call I_CONCAT it will expand it to x##y, but with the values of x and y.
The C preprocessor does just dummy text substitution at compile time.
What means text substitution? The preprocessor will output C code substituting the parameters of the macro with the passed values. It does not matter if you pass a variable or a constant number, you will just get dummy substitution (also called macro "expansion").
Let's go to see how the preprocessor will "expand" #define cat(a,b,c) a##b##c
.
d=cat(1,2,3);
expands to: d=123;
and this is valid code because you have declared int d
.
d=cat(a,b,c);
expands to: d=abc;
and this will not compile since there's no int abc
variable.
What means compile time? It means that this text substitution is done on the source code, and the output disregards the content of the variables passed to the macro. In other words, it does not matters that you have initialized a
, b
, and c
to 1
, 2
, and 3
: the result will be just the concatenation (due to the ##
"token-pasting" preprocessor operator) of the passed values. In your case the result is abc
, which means nothing in your code.
You could also use this function to concatenate 3 integers (the other intcat function above does not work when a 0 is the second or third digit. That is because the log of 0 is negative infinity and when you pass 0 it subtracts 1 from your total).
unsigned intcat(unsigned a, unsigned b, unsigned c)
{
uint8_t ax = a;
uint8_t bx = b;
uint8_t cx = c;
ax = (ax * 100);
bx = (bx * 10);
cx = (cx * 1);
return(ax + bx + cx);
}
精彩评论