118

I'm trying to figure out how I can concatenate a #define'd int to a #define'd string using the C Preprocessor. My compiler is GCC 4.1 on CentOS 5. The solution should also work for MinGW.

I'd like to append a version number onto a string, but the only way I can get it to work is to make a copy of the version number defines as strings.

The closest thing I could find was a method of quoting macro arguments, but it doesn't work for #defines

This is does not work.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER

It doesn't work without the #s either because the values are numbers and it would expand to "/home/user/.myapp" 2 6, which isn't valid C.

This does work, but I don't like having copies of the version defines because I do need them as numbers as well.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING
1

3 Answers 3

243

Classical C preprocessor question....

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

The extra level of indirection will allow the preprocessor to expand the macros before they are converted to strings.

Sign up to request clarification or add additional context in comments.

5 Comments

STR() in this case will give a Narrow string. Is there a variation to convert this to a wide string?
I couldn't say how many times I googled it and copied from this exact answer, but it's going to be in double digits
The first "STR_HELPER" is required because '#' only works with a macro argument. It took me sometime to figure that out..
@clarkttfu, sort of -- yes, # only works with macro arguments. However, the STR_HELPER macro is needed to avoid turning the macro MAJOR_VER into the string "MAJOR_VAR", wheres we want to the result to be "2".
My brain hurts that this can't be done with a single macro... As a lot of other people, used this dozens of times
16

A working way is to write MY_FILE as a parametric macro:

#define MY_FILE(x,y) "/home..." #x #y

EDIT: As noted by "Lindydancer", this solution doesn't expand macros in arguments. A more general solution is using two-step macros:

#define MY_FILE_(x,y) "/home..." #x #y
#define MY_FILE(x,y) MY_FILE_(x,y)

Comments

0

You can do that with BOOST_PP_STRINGIZE:

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" BOOST_PP_STRINGIZE(MAJOR_VER) BOOST_PP_STRINGIZE(MINOR_VER)

5 Comments

Makes me smirk how people throw Boost at everything.
@Frerich: Taking your argument to extreme, people should write their own compilers first in raw machine code, rather than throwing g++ at everything... No point to reinvent the wheel. Good programmers write code, great ones reuse.
@jonescb: just open the boost header and see for yourself.
Yep, I tried it. It did work, but using a Boost header in a C program seems kind of odd to me.
Oh, my bad, did not notice C tag.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.