tuergeist
tuergeist

Reputation: 9391

How to print a pound / hash via C preprocessor?

I need help doing the following:

a preprocessor macro label(x) shall output "#x", e.g.,

#define label(x) ...

if I call label(aname), the output shall be "#aname" (w/o quotes)

I know, that the following tries were errors.

#define label(x) #x   // leads to "x"
#define label(x) \#x  // is \"x"
#define label(x) "#x" // is "#x" (but not the content of x") "#otto"

It may exist a kind of escaped # (pound), but I don't know, how to escape...

Edit: I run "gcc -E test -o test.html" to get the output. The point is: How do I print out a hash mark (#) with a makro only using preprocessor's capabilities?

Upvotes: 9

Views: 9678

Answers (5)

E.M.
E.M.

Reputation: 4547

You can do something like this:

#define f(x) x
#define label(a) f(#)a

I tested this by running it directly through cpp (the C preprocessor) instead of through gcc. Example:

cpp test > test.html

Using the cpp that is part of gcc version 4.0.1.

The only problem I noticed is that I get some extra unwanted output, namely the first 4 lines of the file are as follows:

# 1 "test"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test"

Upvotes: 4

Christoph
Christoph

Reputation: 169613

String literals in C will be concatenated, so you can do

#define label(x) "#" #x

I don't think it's possible without string concatenation (ie without invoking the C compiler as you want to do):

You can do some fancy stuff with additional levels of indirection and I even got the preprocessor to generate the desired output via

#define hash #
#define quote(x) #x
#define in_between(c, d) quote(c ## d)
#define join(c, d) in_between(c, d)
#define label(x) join(hash, x)
label(foo)

The problem is it will also generate an error message as in_between() expands to #foo, which is not an valid preprocessor token. I don't see any way around this.

My advise would be to choose the right tool for the job: switch to another macro language like m4 or even ML/I if you feel adventurous or use a scripting language like PHP or Perl. GPP seems nice as well and might be a better fit.

Upvotes: 3

tuergeist
tuergeist

Reputation: 9391

The answer is:

#define hash #
#define f(x) x
#define label(a) f(hash)a

then

label(foobar)

creates

#foobar

I found it with the help of all of you, but especially wintermute. Thanks a lot!

(Using gcc 4.3.3)

Upvotes: 13

Jonathan Leffler
Jonathan Leffler

Reputation: 754090

I don't think you can, which is not wholly unreasonable since the output of the C preprocessor should not produce an unquoted '#' because that would indicate a pre-processor directive, and you cannot generate pre-processor directives on the fly like that.

In other words, the C preprocessor is a preprocessor for C (and C++) and not a completely general purpose tool.

Either use an alternative macro processor (m4 is the standard recommendation on Unix-like systems), or go about things differently.

For example, have the macro replacement:

#define label(x)    !@!x

Then post-process the output replacing '!@!' with '#'.

(The imake program uses a similar stunt; the C preprocessor does most of the work, but its output doesn't preserve line breaks needed by 'make', so 'imake' uses the notation '@@\' or thereabouts to indicate where line breaks need to be inserted after the C preprocessor has done its worst.)

Upvotes: 4

Neil
Neil

Reputation: 2438

Try:

#define label(x) "#"x

Upvotes: 1

Related Questions