【问题标题】:How to print a pound / hash via C preprocessor?如何通过 C 预处理器打印磅/哈希?
【发布时间】:2010-11-26 01:47:33
【问题描述】:

我需要以下帮助:

预处理器宏标签(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 的井号 (#)?

【问题讨论】:

  • 请问你想做什么?
  • g 是的。我将使用预处理器“创建” html 代码;) label(x) 将用于创建指向锚点的链接,例如,... 我减少了问题的复杂性。
  • 您希望此 HTML 代码作为字符串,在 C 程序中使用,还是作为实际的 HTML 代码,直接进入浏览器?
  • 在这种情况下,我可以建议 C 预处理器不适合这项工作吗?它不是一个强大的文本处理器。它是为 C 语言设计的,并且在该语言中运行良好,但如果您尝试将其用于其他许多方面,则效果会很差。你要打一场艰苦的战斗才能让它做事。这是一个很好的例子——我什至不确定你是否可以在这里做你想做的事。
  • 如果您想使用 C 预处理器生成 Haskell 未装箱的元组,这实际上非常有用,这些元组会被哈希破坏。

标签: c c-preprocessor


【解决方案1】:

答案是:

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

然后

label(foobar)

创造

#foobar

我在你们所有人的帮助下找到了它,尤其是 Wintermute。 非常感谢!

(使用 gcc 4.3.3)

【讨论】:

  • 但这不是您问题的答案:您要求引用的表达式"#foobar"
  • 这是定义好的,还是tuergeist正在使用的特定预处理器实现的函数?
  • 我只想说,不久之后,您可能会发现自己回到这里并提出另一个问题,即如何让 C 预处理器执行 X 或 Y。我希望您能记住我所说的说这是一场艰苦的战斗,你强烈考虑我的建议,为这项工作找到一个新工具。
  • @tuergeist:嗯,这让事情变得更容易;)我建议使用反引号将输出标记为代码而不是双引号 - 这样可以防止我的误解
  • @tuergeist - 啊,经典的“维护别人的聪明黑客”难题。我代表有使用 C 预处理器生成 HTML 的“绝妙”想法的人道歉。
【解决方案2】:

我不认为你可以,这并非完全不合理,因为 C 预处理器的输出不应产生未加引号的 '#',因为这将指示预处理器指令,并且您无法生成预处理器指令那样的苍蝇。

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

要么使用替代的宏处理器(m4 是类 Unix 系统的标准推荐),要么以不同的方式处理。

例如,有宏替换:

#define label(x)    !@!x

然后对替换“!@!”的输出进行后处理带“#”。

(imake 程序使用了类似的特技;C 预处理器完成了大部分工作,但它的输出不保留 'make' 所需的换行符,因此 'imake' 使用符号 '@@\'或在附近指示在 C 预处理器最坏的情况下需要插入换行符的位置。)

【讨论】:

    【解决方案3】:

    你可以这样做:

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

    【讨论】:

    • @tuergeist - 实际上我对它的测试与你略有不同。查看我更新的帖子。
    • 这些第一行没问题,可以忽略。
    • @wintermute:我的 gcc 4.3.3 带来了我之前发布的错误:|但它适用于哈希的定义
    • 可以使用 -P 开关抑制不需要的行。
    【解决方案4】:

    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 看起来也不错,可能更合适。

    【讨论】:

    • 导致 '"#" "string"' 不是 '#string' 请问你是如何测试你的答案的?
    • 在 C 语言中,编写 char *c = "#" "string"; 与编写 char *c = "#string"; 相同 - 该语言连接彼此相邻的字符串文字。因此,这不适用于预处理器,但适用于 C 语言。
    • 正如我所写,我将使用预处理器的输出,不会运行额外的 c 编译器。
    【解决方案5】:

    试试:

    #define label(x) "#"x
    

    【讨论】:

    • 只有在 c 中用作 char* 时才可以
    猜你喜欢
    • 2016-09-19
    • 1970-01-01
    • 2015-07-16
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    相关资源
    最近更新 更多