Alternative Titles (to aid search)
Convert a preprocessor token to a string
How to make a char string from a C macro's value?
Original Question
I would like to use C #define to build literal strings at compile time.
The string are domains that change for debug, release etc.
I would like to some some thing like this:
#ifdef __TESTING
#define IV_DOMAIN example.org //in house testing
#elif __LIVE_TESTING
#define IV_DOMAIN test.example.com //live testing servers
#else
#define IV_DOMAIN example.com //production
#endif
// Sub-Domain
#define IV_SECURE "secure.IV_DOMAIN" //secure.example.org etc
#define IV_MOBILE "m.IV_DOMAIN"
But the preprocessor doesn't evaluate anything within ""
Is there a way around this?
Is this even a good idea?
In C, string literals are concatenated automatically. For example,
const char * s1 = "foo" "bar";
const char * s2 = "foobar";
s1 and s2 are the same string.
So, for your problem, the answer (without token pasting) is
#ifdef __TESTING
#define IV_DOMAIN "example.org"
#elif __LIVE_TESTING
#define IV_DOMAIN "test.example.com"
#else
#define IV_DOMAIN "example.com"
#endif
#define IV_SECURE "secure." IV_DOMAIN
#define IV_MOBILE "m." IV_DOMAIN
There are a couple ways to do this:
if you're dealing with only string literals, you can simply use simply use strings - placing one string literal after another causes the compiler to concatenate them.
if there may be other things than string literals involved (ie., you are creating new identifiers from the macros) use the '##" preprocessor token pasting operator. You'd probably also need to use the '#' 'stringizing operator to make your macros into literal strings.
An example of #1:
#ifdef __TESTING
#define IV_DOMAIN "example.org" //in house testing
#elif __LIVE_TESTING
#define IV_DOMAIN "test.example.com" //live testing servers
#else
#define IV_DOMAIN "example.com" //production
#endif
// Sub-Domain
#define IV_SECURE "secure." IV_DOMAIN //secure.example.org etc
#define IV_MOBILE "m." IV_DOMAIN
And as far as the token pasting operator goes, I don't think that most of the answers that suggested using the token pasting preprocessor operator have actually tried it - it can be tricky to use.
Using the answer that is often suggested will result in a compiler error when you try to use the IV_SECURE macro, because:
#define IV_SECURE "secure."##IV_DOMAIN
expands to:
"secure"example.org
You might want to try to use the '#`' 'stringizing' operator:
#define IV_SECURE "secure." #IV_DOMAIN
But that won't work because it only works on macro arguments - not just any old macro.
one thing to be aware of when you're using the token-paste ('##') or stringizing ('#') preprocessing operators is that you have to use an extra level of indirection for them to work properly in all cases.
If you don't do this and the items passed to the token-pasting operator are macros themselves, you'll get results that are probably not what you want:
#include <stdio.h>
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
#define BAD_PASTE(x,y) x##y
#define BAD_STRINGIFY(x) #x
#define SOME_MACRO function_name
int main()
{
printf( "buggy results:\n");
printf( "%s\n", STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
printf( "\n" "desired result:\n");
printf( "%s\n", STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
}
The output:
buggy results:
SOME_MACRO__LINE__
BAD_PASTE( SOME_MACRO, __LINE__)
PASTE( SOME_MACRO, __LINE__)
desired result:
function_name21
So using your original IV_DOMAIN defines and the utilty macros from above, you could do this to get what you want:
// Sub-Domain
#define IV_SECURE "secure." STRINGIFY( IV_DOMAIN) //secure.domain.org etc
#define IV_MOBILE "m." STRINGIFY( IV_DOMAIN)
Strings that are next together are combined by the C compiler.
#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
const char *asCString = SUBDOMAIN;
NSString *asNSString = #SUBDOMAIN;
I see lots of good and correct answers to your first question, but none to your second, so here's this: I think this is a terrible idea. Why should you have to rebuild your software (particularly the release version) just to change the server name? Also, how will you know which version of your software points at which server? You'll have to build in a mechanism to check at runtime. If it's at all practical on your platform, I recommend you load the domains/URLs from a config file. Only the smallest of embedded platforms may not be "practical" for that purpose :)
Try using the ## operator
#define IV_SECURE secure.##IV_DOMAIN
What you need are the # and ## operators, and automatic string concatenation.
The # preprocessing operator turns the macro parameter into a string. The ## operator pastes two tokens (such as macro parameters) together.
The possibility that comes to mind to me is
#define IV_DOMAIN domain.org
#define IV_SECURE(DOMAIN) "secure." #DOMAIN
which should change IV_SECURE to
#define IV_SECURE "secure." "domain.org"
which will automatically concatenate to "secure.domain.org" (assuming the phases of translation are the same in C as C++).
ANOTHER EDIT: Please, please read the comments, which show how I've managed to get confused. Bear in mind that I am thoroughly experienced in C, although perhaps a touch rusty. I would delete this answer, but I thought I'd leave it as an example of how easy it is to get confused by the C preprocessor.
As others have noted, use token pasting. You should also be aware that macro names like
__TESTING
are reserved in C (don't know about Objective C) for the implementation - you are not allowed to use them in your own code. The reserved names are anything containing double underscores and anything begining with an underscore and an uppercase letter.
Related
I am curious if any of you can think of a way upon macro expansion to repeat the macro itself. Here is an incredibly small scale version of an overall bigger problem:
#include<stdio.h>
#define LETTERS\
X(A)\
X(B)\
X(C)\
X(D)
#define X(L) #L
int main(int nargs,char** args)
{
printf("%s\n",LETTERS);
return 0;
}
Output: ABCD
Desired output: AABCD BABCD CABCD DABCD
The desired output is clearly similar to a nested (N^2) loop over whatever input data.
The stringification doesn't matter, it's only there for compilation.
There are some obvious and some not so obvious solutions to the desired output.
One is to make a complete copy of the macro, then between each X element, you simply refer to the copy. This would be wasteful and I don't want to do it. Obviously you can't refer to the macro itself due to recursion. I have made many attempts to find a decent solution, and won't list all of them as it would take up way too much time. I am open to solutions that use other macros to repeat or expand the original, or solutions that use janky forms of recursion.
#include<stdio.h>
#define LETTERS_COPY\
X(A)\
X(B)\
X(C)\
X(D)
#define LETTERS\
X(A)\
LETTERS_COPY\
X(B)\
LETTERS_COPY\
X(C)\
LETTERS_COPY\
X(D)\
LETTERS_COPY
#define X(L) #L
int main(int nargs,char** args)
{
printf("%s\n",LETTERS);
return 0;
}
Again, this builds just fine and works, but requires a complete duplicate of the original data, interjecting itself between each X element.
If you use an iterating macro, like how one is defined in the P99 macro utility collection, then it becomes much easier to solve.
Since we intend to define an iterating macro, we don't need X-macros on the letters anymore.
#define LETTERS \
A \
,B \
,C \
,D
Below is a simplified iterating macro that supports up to 5 arguments. Hopefully you see how to extend the implementation if you need more.
#define XX(X, ...) \
XX_X(__VA_ARGS__, XX_5, XX_4, XX_3, XX_2, XX_1) \
(X, __VA_ARGS__)
#define XX_X(_1,_2,_3,_4,_5,X,...) X
#define XX_1(X, _) X(_)
#define XX_2(X, _, ...) X(_) XX_1(X, __VA_ARGS__)
#define XX_3(X, _, ...) X(_) XX_2(X, __VA_ARGS__)
#define XX_4(X, _, ...) X(_) XX_3(X, __VA_ARGS__)
#define XX_5(X, _, ...) X(_) XX_4(X, __VA_ARGS__)
So, if you invoke XX(X, LETTERS), it will expand into the X-macro version of LETTERS you had before.
The magic of the XX() macro is the meta nature of the XX_X() macro, which selects the right numeric macro to use. The numeric macro is passed in reverse order to the XX_X() macro when it is invoked by XX(). This makes it so that XX_X() selects a lower numeric macro if __VA_ARGS__ contains fewer arguments.
Now, we create a macro to turn the argument into a string:
#define STR(X) STR_(X)
#define STR_(X) #X
This allows you to easily create the string with all your letters.
And printing your iterative output just needs another macro.
int main () {
const char *letters = XX(STR, LETTERS);
#define LETTERS_PRINT(X) printf("%s%s\n", #X, letters);
XX(LETTERS_PRINT, LETTERS)
}
We see that the solution applies XX() twice. Once to create the string of all your letters. Once to create the output, which is prepending each letter to the combined letters.
Try it online!
For anyone wondering, the best I could do was make a second X macro that takes 2 args, and the outer list becomes a function macro that takes a single arg. This lets you pass data to the list, and to the second x macro, while still being able to unpack either X macro however you like.
#include<stdio.h>
#define _CAT(A,B) A##B
#define CAT(A,B) _CAT(A,B)
#define _STR(S) #S
#define STR(S) _STR(S)
#define LETTERS(L)\
XX(L,X(A))\
XX(L,X(B))\
XX(L,X(C))\
XX(L,X(D))
int main(int nargs,char** args)
{
#define X(L) L
#define XX(L1,L2) STR(CAT(L1,L2))
printf("%s\n",LETTERS(A));
printf("%s\n",LETTERS(B));
printf("%s\n",LETTERS(C));
printf("%s\n",LETTERS(D));
#undef XX
#undef X
return 0;
}
I am trying to implement VERSION macro for my program, that is to be changed under certain circumstances.
macro VERSION is defined via Makefile (git info is put there) and is a string.
Now I have a set of #define'd switches and I want VERSION to reflect which of them are on. This looks now like the follows (main.h):
#define COMPLEX_DEPOSITION // This is switch. later in code it is used in #ifdef...#endif construction.
#ifdef COMPLEX_DEPOSITION
#define CD "_COMP_DEP" // this is the string I want to put in the end of VERSION
#define VERSION_ VERSION CD
#undef VERSION // this is to suppress 'macro redefinition' warning
#define VERSION VERSION_
#undef VERSION_
#endif
Well, I get a lot of errors, most of which make me think that C preprocessor works with lines in file in random order:(
Later I have an even more complex thing that is intended to make VERSION -> VERSION_WLT_GAP_2
#define WIRESLIFETIMES
#ifdef WIRESLIFETIMES
#define GAP 2
#define VERSION_ (VERSION ## "_WLT_GAP_" ## #GAP)
#define VERSION VERSION_
#undef VERSION_
#endif
and I got no idea what to do and if this is even possible
String literals concatenate naturally when placed next to each other
"foo" "bar" is the same as "foobar".
As for the second example, you probably want:
#define CAT_(A,B) A##B
#define CAT(A,B) CAT_(A,B)
#define GAP 2
#define VERSION CAT(VERSION_WLT_GAP_ , GAP)
VERSION //expands to VERSION_WLT_GAP_2
I recommend playing with gcc -E/clang -E a bit, to learn how macros work,
before trying to compose anything complex with them.
Well, the answer seems to be the following:
// https://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation
// Concatenate preprocessor tokens A and B without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define PPCAT_NX(A, B) A ## B
// Concatenate preprocessor tokens A and B after macro-expanding them.
#define PPCAT(A, B) PPCAT_NX(A, B)
// Turn A into a string literal without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define STRINGIZE_NX(A) #A
// Turn A into a string literal after macro-expanding it.
#define STR(A) STRINGIZE_NX(A)
#define COMPLEX_DEPOSITION
#ifdef COMPLEX_DEPOSITION
#define CD "_COMPDEP"
#else
#define CD ""
#endif
#define WIRESLIFETIMES
#ifdef WIRESLIFETIMES
#define GAP 2
#define WLT STR(PPCAT(_WLT:G, GAP))
#define DISABLE_METROPOLIS
#else
#define WLT ""
#endif
#define VERSION VERSIONX CD WLT
which produces V008.1-11-g68a9c89cb4-dirty_COMPDEP_WLT:G2 and I am happy with it.
Must be noted that I changed -DVERSION=... to -DVERSIONX=... inside Makefile
I have code similar to
#define LIST_OF_VARIABLES \
X(value1) \
X(value2) \
X(value3)
as explained in https://en.wikipedia.org/wiki/X_Macro
Now I have the need to make the LIST_OF_VARIABLES configurable at compile time
So it could effectively be e.g.
#define LIST_OF_VARIABLES \
X(default_value1) \
X(cust_value2) \
X(default_value3)
or e.g.
#define LIST_OF_VARIABLES \
X(default_value1) \
X(default_value2) \
X(cust_value3)
depending on some macros previously defined. The LIST_OF_VARIABLES is long and the customizations are relatively small. I would not like to copy the long list for each customization, because that will cause maintenance issues (the DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). As a matter of fact the LIST_OF_VARIABLES should be in one file and the
customizations elsewhere (either another file or just -D options in the Makefile)
In pseudo-code I was thinking of something like
#define X(arg) \
#ifdef CUST_##arg \
Y(CUST_##arg) \
#else \
Y(DEFAULT_##arg) \
#endif
And then use the X-macros under the name Y.
But of course that does not work, because a macro cannot contain preprocessor
directives.
What would be a way to achieve this? C is a must (no templates or Boost
macros), gcc specific solutions are acceptable.
I think that what you have to do is along the lines of:
#ifdef USE_DEFAULT_VALUE1
#define X_DEFAULT_VALUE1 X(default_value1)
#else
#define X_DEFAULT_VALUE1 /* omitted */
#endif
#ifdef USE_DEFAULT_VALUE2
#define X_DEFAULT_VALUE2 X(default_value2)
#else
#define X_DEFAULT_VALUE2 /* omitted */
#endif
#ifdef USE_DEFAULT_VALUE3
#define X_DEFAULT_VALUE3 X(default_value3)
#else
#define X_DEFAULT_VALUE3 /* omitted */
#endif
#ifdef USE_CUST_VALUE1
#define X_CUST_VALUE1 X(cust_value1)
#else
#define X_CUST_VALUE1 /* omitted */
#endif
#ifdef USE_CUST_VALUE2
#define X_CUST_VALUE2 X(cust_value2)
#else
#define X_CUST_VALUE2 /* omitted */
#endif
#define LIST_OF_VARIABLES \
X_DEFAULT_VALUE1 \
X_DEFAULT_VALUE2 \
X_DEFAULT_VALUE3 \
X_CUST_VALUE1 \
X_CUST_VALUE2 \
You then need to define USE_DEFAULT_VALUE1 etc as required for the specific configuration you are after.
As long as you always need the items in the same order, this is sufficient. If you need them in different orders, then you conditionally define LIST_OF_VARIABLES in the different sequences.
Answering myself.
With help of the comments I came up with a solution that works and meets most
requirements I had mentioned
With the "main code"
$cat main.c
#ifndef VALUE1
#define VALUE1 value1
#endif
#ifndef VALUE2
#define VALUE2 value2
#endif
#ifndef VALUE3
#define VALUE3 value3
#endif
#define LIST_OF_VARIABLES \
X(VALUE1) \
X(VALUE2) \
X(VALUE3)
and a customization file like
$cat cust1
-DVALUE2=value2cust
the code can be compiled using (GNUmake pseudo syntax)
$(CC) $(CFLAGS) $(shell cat cust1) main.c
Actually having the extra indirection with every value defined on a single
line is good, because it allows commenting the values. That would not have
been possible with the continuation lines in the single LIST_OF_VARIABLES macro.
Edit: Not true. A COMMENT(foo) macro expanding to nothing would have solved that issue, too. (Credit: Got the idea from the answer posted by #Jonathan Leffer.)
However the approach does not yet meet the following requirements I hadn't mentioned
no ugly boilerplate code (all these #ifndef lines are not really nice)
customization should also make it possible to drop default values from the
list altogether or add completely new values (yes, this could probably be
done with some ugly dummy code already now)
So not really satisfied yet with my own answer. Need to think about the
approach from the Dr. Dobbs article a bit more, maybe that can be used.
Open for better answers.
Given further context, it appears you want to be able to cherry pick individual values from your list at compile time. I think you might be interested in a preprocessor switch, which can accomplish what you're using preprocessor conditionals for with a lot less boilerplate.
Generic preprocessor switch
Here's a brief framework:
#define GLUEI(A,B) A##B
#define GLUE(A,B) GLUEI(A,B)
#define SECONDI(A,B,...) B
#define SECOND(...) SECONDI(__VA_ARGS__,,)
#define SWITCH(NAME_, PATTERN_, DEFAULT_) SECOND(GLUE(NAME_,PATTERN_), DEFAULT_)
SWITCH macro usage
Invoke SWITCH(MY_PREFIX_,SPECIFIC_IDENTIFIER,DEFAULT_VALUE) to expand everything that is not a matching pattern to DEFAULT_VALUE. Things that are a matching pattern can expand to whatever you map them to.
To create a matching pattern, define an object like macro called MY_PREFIX_SPECIFIC_IDENTIFIER, whose replacement list consists of a single comma followed by the value you want the SWITCH to expand to in this case.
The magic here is simply that SWITCH builds a hidden token, giving it a chance to expand (well, in this implementation SECOND's indirection is also significant), and inject a new second argument to SECOND if it's defined. Nominally this new token isn't defined; in such cases, it simply becomes the first argument to SECOND, which just discards it, never to be seen again.
For example, given the above macros:
#define CONTRACT_IDENTIFIER_FOR_DEFAULT , overridden_id_for_default
#define CONTRACT_IDENTIFIER_FOR_SIGNED , overridden_id_for_signed
SWITCH(CONTRACT_IDENTIFIER_FOR_, DRAFT , draft )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DRAWN , drawn )
SWITCH(CONTRACT_IDENTIFIER_FOR_, PROOFED , proofed )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DELIVERED , delivered )
SWITCH(CONTRACT_IDENTIFIER_FOR_, SIGNED , signed )
SWITCH(CONTRACT_IDENTIFIER_FOR_, FULFILLED , fulfilled )
SWITCH(CONTRACT_IDENTIFIER_FOR_, DEFAULT , default )
...will expand to:
draft
drawn
proofed
delivered
overridden_id_for_signed
fulfilled
overridden_id_for_default
Decorated X Macros
Assuming you wish to give your values names, and simply replace cherry picked values from the command line, you can make use of SWITCH to do something like this:
#define VARVALUE(N_,V_) SWITCH(VALUE_FOR_, N_, V_)
#define LIST_OF_VARIABLES \
X(VARVALUE(value1, default_value1)) \
X(VARVALUE(value2, default_value2)) \
X(VARVALUE(value3, default_value3))
The VARVALUE macros will be applied first in this form. To override a specific value, you can define your pattern matcher using either a #define:
#define VALUE_FOR_value2 , custom_value2
...or on the command line/makefile:
CFLAGS += -DVALUE_FOR_value2=,custom_value2
Disable/insertion using switch macro
To support disabling individual items safely, nest two switches and add an EAT macro to catch the entry:
#define EAT(...)
#define SELECT_ITEM_MACRO_FOR_STATE_ON , X
#define X_IF_ENABLED(N_, V_) \
SWITCH(SELECT_ITEM_MACRO_FOR_STATE_, SWITCH(ENABLE_VALUE_, N_, ON), EAT) \
(SWITCH(VALUE_FOR_, N_, V_))
#define LIST_OF_VARIABLES \
X_IF_ENABLED(value1, default_value1) \
X_IF_ENABLED(value2, default_value2) \
X_IF_ENABLED(value3, default_value3)
Just as before, individual macros can be overridden using VALUE_FOR_valuex pattern macros, but this also allows disabling items using ENABLE_VALUE_valuex macros, which can be set to anything but ,ON to disable that item.
Similarly, one way to add support for inserting values is to flip the idea:
#define ADD_ITEM_MACRO_FOR_STATE_EAT , EAT
#define X_IF_ADDED(N_) \
SWITCH(ADD_ITEM_MACRO_FOR_STATE_, SWITCH(VALUE_FOR_, N_, EAT), X) \
(SECOND(GLUE(VALUE_FOR_,N_)))
#define LIST_OF_VARIABLES \
X_IF_ENABLED(value1, default_value1) \
X_IF_ENABLED(value2, default_value2) \
X_IF_ENABLED(value3, default_value3) \
X_IF_ADDED(value4) \
X_IF_ADDED(value5) \
X_IF_ADDED(value6)
...this allows you to define VALUE_FOR_value4 as a a pattern macro, but by default will expand to nothing.
Summary
The framework supporting setting, removing, or inserting values winds up being:
#define GLUEI(A,B) A##B
#define GLUE(A,B) GLUEI(A,B)
#define SECONDI(A,B,...) B
#define SECOND(...) SECONDI(__VA_ARGS__,,)
#define SWITCH(NAME_, PATTERN_, DEFAULT_) SECOND(GLUE(NAME_,PATTERN_), DEFAULT_)
#define EAT(...)
#define SELECT_ITEM_MACRO_FOR_STATE_ON , X
#define X_IF_ENABLED(N_, V_) \
SWITCH(SELECT_ITEM_MACRO_FOR_STATE_, SWITCH(ENABLE_VALUE_, N_, ON), EAT) \
(SWITCH(VALUE_FOR_, N_, V_))
#define ADD_ITEM_MACRO_FOR_STATE_EAT , EAT
#define X_IF_ADDED(N_) \
SWITCH(ADD_ITEM_MACRO_FOR_STATE_, SWITCH(VALUE_FOR_, N_, EAT), X) \
(SECOND(GLUE(VALUE_FOR_,N_)))
Given this framework, your list macro would be comprised of a series of X(value), X_IF_ENABLED(name,default_value), and/or X_IF_ADDED(name) values, where:
X(value) can be used to always insert a call to the X macro with value
X_IF_ENABLED(name,default_value) will call X with default_value, allowing you to override the default based on name.
X_IF_ADDED(name) will provide an "empty slot" with name, which will do nothing unless you override that slot.
Overriding slots is done by defining VALUE_FOR_name to expand to ,replacement. Disabling enabled slots is done by defining ENABLE_VALUE_name to expand to ,OFF.
Demo showing change, removal, addition using command line
How can one define a C macro IFARGS(YES, NO, ...) such that invoking IFARGS with no additional arguments produces NO, and invoking IFARGS with one or more arguments produces YES?
I have an answer using GCC (see below), but I'd prefer one for C99 if possible (or a proof of its impossibility).
In C99 it is possible to detect if a macro argument is empty, but making that robust against all odds that may appear in that argument (arguments that are themselves expanding, contain () and stuff like that) is difficult. My macro package P99 implements such a thing, so you wouldn't have to worry too much. With that your macro can be implemented as
#define IFARGS(YES, NO, ...) P99_IF_EMPTY(__VA_ARGS__)(YES(__VA__ARGS__))(NO())
As its name indicates, P99 is only building on C99 features for that.
#define GET(_0, _1) _0 // Return the first of two arguments
#define GET_(_0, _1) _1 // Return the second of two arguments
#define JOIN(_0, _1) _0 ## _1 // Concatenate two arguments
#define EJOIN(_0, _1) JOIN(_0, _1) // Expand macros and concatenate
#define FIRST(_, ...) _ // Truncate everything after first comma
#define EFIRST(_) FIRST(_) // Expand argument and pass to FIRST
#define REST(_0, ...) __VA_ARGS__ // Remove everything before first comma
#define GET_GET(...) \
EJOIN(GET, EFIRST(REST(,,##__VA_ARGS__ _))) // Branch between GET and GET_
#define IFARGS(YES, NO, ...) GET_GET(__VA_ARGS__)(YES, NO)
Note that if this were possible in C99, then it would be possible to simulate ##__VA_ARGS__, like so:
#define PREPEND_COMMA(...) , __VA_ARGS__
#define NO_COMMA()
#define PREPEND_COMMA_IF_NONEMPTY(...) IFARGS(PREPEND_COMMA, NO_COMMA, __VA_ARGS__)(__VA_ARGS__)
Then any instance of , ##__VA_ARGS__ could be replaced by PREPEND_COMMA_IF_NONEMPTY(__VA_ARGS__).
As mentioned in many of my previous questions, I'm working through K&R, and am currently into the preprocessor. One of the more interesting things — something I never knew before from any of my prior attempts to learn C — is the ## preprocessor operator. According to K&R:
The preprocessor operator ##
provides a way to concatenate actual
arguments during macro expansion. If a
parameter in the replacement text is
adjacent to a ##, the parameter is
replaced by the actual argument, the
## and surrounding white space are
removed, and the result is re-scanned.
For example, the macro paste
concatenates its two arguments:
#define paste(front, back) front ## back
so paste(name, 1) creates the token
name1.
How and why would someone use this in the real world? What are practical examples of its use, and are there gotchas to consider?
One thing to be aware of when you're using the token-paste ('##') or stringizing ('#') preprocessing operators is that you have to use an extra level of indirection for them to work properly in all cases.
If you don't do this and the items passed to the token-pasting operator are macros themselves, you'll get results that are probably not what you want:
#include <stdio.h>
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
#define BAD_PASTE(x,y) x##y
#define BAD_STRINGIFY(x) #x
#define SOME_MACRO function_name
int main()
{
printf( "buggy results:\n");
printf( "%s\n", STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
printf( "\n" "desired result:\n");
printf( "%s\n", STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
}
The output:
buggy results:
SOME_MACRO__LINE__
BAD_PASTE( SOME_MACRO, __LINE__)
PASTE( SOME_MACRO, __LINE__)
desired result:
function_name21
CrashRpt: Using ## to convert macro multi-byte strings to Unicode
An interesting usage in CrashRpt (crash reporting library) is the following:
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
//Note you need a WIDEN2 so that __DATE__ will evaluate first.
Here they want to use a two-byte string instead of a one-byte-per-char string. This probably looks like it is really pointless, but they do it for a good reason.
std::wstring BuildDate = std::wstring(WIDEN(__DATE__)) + L" " + WIDEN(__TIME__);
They use it with another macro that returns a string with the date and time.
Putting L next to a __ DATE __ would give you a compiling error.
Windows: Using ## for generic Unicode or multi-byte strings
Windows uses something like the following:
#ifdef _UNICODE
#define _T(x) L ## x
#else
#define _T(x) x
#endif
And _T is used everywhere in code
Various libraries, using for clean accessor and modifier names:
I've also seen it used in code to define accessors and modifiers:
#define MYLIB_ACCESSOR(name) (Get##name)
#define MYLIB_MODIFIER(name) (Set##name)
Likewise you can use this same method for any other types of clever name creation.
Various libraries, using it to make several variable declarations at once:
#define CREATE_3_VARS(name) name##1, name##2, name##3
int CREATE_3_VARS(myInts);
myInts1 = 13;
myInts2 = 19;
myInts3 = 77;
Here's a gotcha that I ran into when upgrading to a new version of a compiler:
Unnecessary use of the token-pasting operator (##) is non-portable and may generate undesired whitespace, warnings, or errors.
When the result of the token-pasting operator is not a valid preprocessor token, the token-pasting operator is unnecessary and possibly harmful.
For example, one might try to build string literals at compile time using the token-pasting operator:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a##+##b)
#define NS(a, b) STRINGIFY(a##::##b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
On some compilers, this will output the expected result:
1+2 std::vector
On other compilers, this will include undesired whitespace:
1 + 2 std :: vector
Fairly modern versions of GCC (>=3.3 or so) will fail to compile this code:
foo.cpp:16:1: pasting "1" and "+" does not give a valid preprocessing token
foo.cpp:16:1: pasting "+" and "2" does not give a valid preprocessing token
foo.cpp:16:1: pasting "std" and "::" does not give a valid preprocessing token
foo.cpp:16:1: pasting "::" and "vector" does not give a valid preprocessing token
The solution is to omit the token-pasting operator when concatenating preprocessor tokens to C/C++ operators:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a+b)
#define NS(a, b) STRINGIFY(a::b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
The GCC CPP documentation chapter on concatenation has more useful information on the token-pasting operator.
This is useful in all kinds of situations in order not to repeat yourself needlessly. The following is an example from the Emacs source code. We would like to load a number of functions from a library. The function "foo" should be assigned to fn_foo, and so on. We define the following macro:
#define LOAD_IMGLIB_FN(lib,func) { \
fn_##func = (void *) GetProcAddress (lib, #func); \
if (!fn_##func) return 0; \
}
We can then use it:
LOAD_IMGLIB_FN (library, XpmFreeAttributes);
LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
LOAD_IMGLIB_FN (library, XpmReadFileToImage);
LOAD_IMGLIB_FN (library, XImageFree);
The benefit is not having to write both fn_XpmFreeAttributes and "XpmFreeAttributes" (and risk misspelling one of them).
A previous question on Stack Overflow asked for a smooth method of generating string representations for enumeration constants without a lot of error-prone retyping.
Link
My answer to that question showed how applying little preprocessor magic lets you define your enumeration like this (for example) ...;
ENUM_BEGIN( Color )
ENUM(RED),
ENUM(GREEN),
ENUM(BLUE)
ENUM_END( Color )
... With the benefit that the macro expansion not only defines the enumeration (in a .h file), it also defines a matching array of strings (in a .c file);
const char *ColorStringTable[] =
{
"RED",
"GREEN",
"BLUE"
};
The name of the string table comes from pasting the macro parameter (i.e. Color) to StringTable using the ## operator. Applications (tricks?) like this are where the # and ## operators are invaluable.
You can use token pasting when you need to concatenate macro parameters with something else.
It can be used for templates:
#define LINKED_LIST(A) struct list##_##A {\
A value; \
struct list##_##A *next; \
};
In this case LINKED_LIST(int) would give you
struct list_int {
int value;
struct list_int *next;
};
Similarly you can write a function template for list traversal.
The main use is when you have a naming convention and you want your macro to take advantage of that naming convention. Perhaps you have several families of methods: image_create(), image_activate(), and image_release() also file_create(), file_activate(), file_release(), and mobile_create(), mobile_activate() and mobile_release().
You could write a macro for handling object lifecycle:
#define LIFECYCLE(name, func) (struct name x = name##_create(); name##_activate(x); func(x); name##_release())
Of course, a sort of "minimal version of objects" is not the only sort of naming convention this applies to -- nearly the vast majority of naming conventions make use of a common sub-string to form the names. It could me function names (as above), or field names, variable names, or most anything else.
I use it in C programs to help correctly enforce the prototypes for a set of methods that must conform to some sort of calling convention. In a way, this can be used for poor man's object orientation in straight C:
SCREEN_HANDLER( activeCall )
expands to something like this:
STATUS activeCall_constructor( HANDLE *pInst )
STATUS activeCall_eventHandler( HANDLE *pInst, TOKEN *pEvent );
STATUS activeCall_destructor( HANDLE *pInst );
This enforces correct parameterization for all "derived" objects when you do:
SCREEN_HANDLER( activeCall )
SCREEN_HANDLER( ringingCall )
SCREEN_HANDLER( heldCall )
the above in your header files, etc. It is also useful for maintenance if you even happen to want to change the definitions and/or add methods to the "objects".
SGlib uses ## to basically fudge templates in C. Because there's no function overloading, ## is used to glue the type name into the names of the generated functions. If I had a list type called list_t, then I would get functions named like sglib_list_t_concat, and so on.
I use it for a home rolled assert on a non-standard C compiler for embedded:
#define ASSERT(exp) if(!(exp)){ \
print_to_rs232("Assert failed: " ## #exp );\
while(1){} //Let the watchdog kill us
I use it for adding custom prefixes to variables defined by macros. So something like:
UNITTEST(test_name)
expands to:
void __testframework_test_name ()
One important use in WinCE:
#define BITFMASK(bit_position) (((1U << (bit_position ## _WIDTH)) - 1) << (bit_position ## _LEFTSHIFT))
While defining register bit description we do following:
#define ADDR_LEFTSHIFT 0
#define ADDR_WIDTH 7
And while using BITFMASK, simply use:
BITFMASK(ADDR)
It is very useful for logging. You can do:
#define LOG(msg) log_msg(__function__, ## msg)
Or, if your compiler doesn't support function and func:
#define LOG(msg) log_msg(__file__, __line__, ## msg)
The above "functions" logs message and shows exactly which function logged a message.
My C++ syntax might be not quite correct.