How to print a pound / hash via C preprocessor?

前端 未结 5 1665
失恋的感觉
失恋的感觉 2021-01-12 00:20

I need help doing the following:

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

#define label(x) ...

if I call label(anam

相关标签:
5条回答
  • 2021-01-12 00:55

    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"
    
    0 讨论(0)
  • 2021-01-12 00:59

    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.)

    0 讨论(0)
  • 2021-01-12 00:59

    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.

    0 讨论(0)
  • 2021-01-12 01:05

    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)

    0 讨论(0)
  • 2021-01-12 01:10

    Try:

    #define label(x) "#"x
    
    0 讨论(0)
提交回复
热议问题