【问题标题】:CPP: Escaping macro identifiersCPP:转义宏标识符
【发布时间】:2023-03-15 09:03:01
【问题描述】:

有没有办法在 c 预处理器 (cpp) 中转义宏名称(标识符)?

我想用可读的宏名称条件化一些网络代码(html、css...)。

条件 css 文件示例:

/*root*/
some rootcode

#if height==480
/* height 480 */
.page {
    line-height:23px;
}

#elif height<480
/* height < 480 */
.page {
    line-height:46px;
}

#endif

调用

cpp -P -D height=480 -oout.css css.ccss

导致(删除换行符后)

some rootcode
.page {
    line-480:23px;
}

但是“line-480”是错误的。

有没有办法在代码中转义“高度”而不更改宏名称或对其进行字符串化?

【问题讨论】:

  • 这是大多数宏都使用大写字母的原因之一。
  • 但是大写marco标识符一般不会解决问题,只能最小化它。想象一个宏标识符“A”和一个带有文本的 html 站点。然后每个 A 都将替换为宏的值!
  • 通过使用大写和用下划线装饰等技巧,您可以解决您的问题,即使解决方案与您在问题中描述的不同.
  • 我认为 CPP 不是完成这项任务的好工具。
  • 恭喜:这是我见过的最可疑的 CPP 用法之一。

标签: c++ macros


【解决方案1】:

您可以:

1) 取消定义宏:

#undef height

2) 使用类似标准的大写字母重命名宏:

#define HEIGHT

3) 在处理文件之前使用守卫:

#if height==480
#define HEIGHT_480
#undef height
#endif

#if height>480
#define HEIGHT_OVER_480
#undef height
#endif

/*root*/
some rootcode

#if HEIGHT_480
/* height 480 */
.page {
    line-height:23px;
}

#elif HEIGHT_OVER_480
/* height < 480 */
.page {
    line-height:46px;
}

#endif

第一个在取消定义后丢失信息。如果大量使用宏,第二个是不切实际的。

第三个是 IMO 的最佳选择。我已经看到它在生产代码中使用,这样的东西是必要的。

【讨论】:

  • 我稍微简化了我的上下文。取消定义不是选项,因为 cpp 调用应该在运行时进行,并且重新定义(在每个新的 ifdef 之前)不可能使用静态包含。大写可以解决所有基于文本的文档中的一些问题,但不是所有问题。守卫是个好主意,但随后必须检查,所有代码片段都没有使用这个新名称。尽量减少故障数量是个好主意,但不是解决一般问题的方法。
  • @Adreamus 我不明白。运行时与预处理器定义(宏)无关。这些甚至在编译之前就已处理,更不用说运行时了。
  • 如果我有很多标识符。一种可能的解决方案是在每个 #if 或 #elif 前面包含一个“define.file”(#define height = 1,#define os = 2),在此行之后包含一个“undef.file”(#undef height , #undef 操作系统)。但是这个文件是可变的,并不总是在同一个地方。
  • @Adreamus 好吧,对于像您描述的那样动态的系统,您实际上不能拥有任何静态的东西(除非您当然想构建解析器或其他东西)。我很好奇自己是否存在其他解决方案,但我个人现在想不出。
【解决方案2】:

我尝试了 Luchian Grigore 的想法来取消定义使用的文件名,我找到了一个(几乎)通用的解决方案:

在条件句的开头包含一个“define.file”,在给定条件之后包含一个“undefine.file”。

所以问题被简化为两个必须保留的宏名称:DEFINEFILE 和 UNDEFINEFILE。但这两个宏可以使用它们的哈希码或随机名称进行加密,以避免在条件文本中使用这些名称。

“define.file”:

#define height 480
#define os 1

“未定义文件”

#undef height
#undef os

"conditionalcss.ccss"

/*root*/
some rootcode

#include __DEFINEFILENAMEPATH__

#if height==480
#include __UNDEFINEFILENAMEPATH__
/* height 480 */
.page {
    line-height:23px;
}
#include __DEFINEFILENAMEPATH__

#elif height<480
#include __UNDEFINEFILENAMEPATH__
/* height > 480 */
.page {
    line-height:46px;
}
#include __DEFINEFILENAMEPATH__

#endif

#if os==1
#include __UNDEFINEFILENAMEPATH__
os is windows (if 1 refers to windows)
and height also undefined i hope
#endif

最后是带有参数定义和取消定义文件的 cppcall:

cpp -P -D __DEFINEFILENAMEPATH__="\"define.file\"" -D __UNDEFINEFILENAMEPATH__="\"undefine.file\"" -oout.css css.ccss

有了这个想法,得到的“out.css”看起来像:

some rootcode
.page {
    line-height:23px;
}
os is windows (if 1 refers to windows)
and height also undefined i hope

此解决方案只有两个宏的缺点,并且由于多次导入而可能导致性能不佳。

我希望它可以帮助其他人解决他们的问题。

问候 梦想

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 2011-10-14
    • 2021-11-16
    • 2019-08-25
    相关资源
    最近更新 更多