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 macropaste
concatenates its two arguments:
#define paste(front, back) front ## back
so
paste(name, 1)
creates the tokenname1
.
How and why would someone use this in the real world? What are practical examples of its use, and are there gotchas to consider?
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:
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:
expands to something like this:
This enforces correct parameterization for all "derived" objects when you do:
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".
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:
The output:
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:We can then use it:
The benefit is not having to write both
fn_XpmFreeAttributes
and"XpmFreeAttributes"
(and risk misspelling one of them).I use it for a home rolled assert on a non-standard C compiler for embedded:
I use it for adding custom prefixes to variables defined by macros. So something like:
expands to: