代码之家  ›  专栏  ›  技术社区  ›  tuergeist

如何通过C预处理器打印一个磅/哈希?

  •  8
  • tuergeist  · 技术社区  · 15 年前

    我需要帮助进行以下操作:

    预处理器宏标签(X)应输出“X”,例如:

    #define label(x) ...
    

    如果我调用label(aname),则输出应为“aname”(不带引号)

    我知道,下面的尝试是错误的。

    #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"
    

    它可能存在一种逃犯(磅),但我不知道,如何逃走…

    编辑 :我运行“gcc-e test-o test.html”获取输出。重点是:我如何用makro打印哈希标记(),只使用预处理器的功能?

    5 回复  |  直到 10 年前
        1
  •  13
  •   tuergeist    15 年前

    答案是:

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

    然后

    label(foobar)
    

    创造

    #foobar
    

    我是在……的帮助下找到的。 你们所有人 尤其是冬季静音。 谢谢!

    (使用GCC 4.3.3)

        2
  •  4
  •   Jonathan Leffler vy32    15 年前

    我不认为你能,这不是完全不合理的,因为C预处理器的输出不应该产生一个未加引号的“”,因为这意味着一个预处理器指令,而你不能像那样即时生成预处理器指令。

    换句话说,C预处理器是C(和C++)的预处理器,而不是一个完全通用的工具。

    使用另一个宏处理器( m4 是在类Unix系统上的标准建议),还是以不同的方式进行。

    例如,使用宏替换:

    #define label(x)    !@!x
    

    然后对输出进行后处理替换'!@!用“丫”。

    (The imake 程序使用类似的特技;C预处理器完成大部分工作,但其输出不保留“make”所需的换行符,因此“imake”使用符号“@@\”或其左右来指示C预处理器完成最差工作后需要插入换行符的位置。)

        3
  •  4
  •   E.M.    15 年前

    你可以这样做:

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

    我通过直接运行来测试这个 cpp (C预处理器)而不是通过 gcc . 例子:

    cpp test > test.html
    

    使用属于GCC 4.0.1版的CPP。

    我注意到的唯一问题是,我得到了一些多余的输出,即文件的前4行如下:

    # 1 "test"
    # 1 "<built-in>"
    # 1 "<command line>"
    # 1 "test"
    
        4
  •  3
  •   Christoph    15 年前

    C中的字符串文本将被连接,因此可以

    #define label(x) "#" #x
    

    我认为没有字符串连接是不可能的(即不调用C编译器,如您所希望的那样):

    你可以用额外的间接级别做一些花哨的工作,我甚至得到了预处理器来通过

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

    问题是它还将生成一条错误消息 in_between() 扩展到 #foo ,这不是有效的预处理器标记。我对此一无所知。

    我的建议是为工作选择合适的工具:如果你觉得有冒险精神,或者使用像php或perl这样的脚本语言,可以切换到另一种宏语言,比如m4甚至ml/i。 GPP 看起来也不错,可能更合适。

        5
  •  1
  •   Neil    15 年前

    尝试:

    #define label(x) "#"x