tags:

views:

104

answers:

6

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()
{
int 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;
}
+3  A: 

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.

Moron
+1  A: 

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
Michael Mrozek
+8  A: 

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.

Jerry Coffin
On other words, the preprocessor deals with tokens and nothing more.
GMan
+1  A: 

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);
}
pcent
+1  A: 

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.

smerlin
A: 

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.

Lorenzo