【问题标题】:GCC macro expansion arguments inside string字符串内的 GCC 宏扩展参数
【发布时间】:2011-07-13 22:58:10
【问题描述】:

我有这样的情况

#define PRE 0xF1

#define SR0 0B0000
#define SR1 0B0001
#define SR2 0B0010
#define SR3 0B0011

#define VIOTA(A0)  asm(".byte PRE, A0")

int main()
{
  VIOTA(SR1);
  return 0;
}

我有一个扩展的顶级宏,但是扩展包含更多宏。这些没有被扩展并导致一些问题。

我希望的行为是结束扩展是

asm(".byte 0xF1, 0B0000")

这里的内部宏已被扩展。我真的不确定我做错了什么。有什么建议吗?

【问题讨论】:

  • 补充一点信息。是的,引号是这里的问题,但重要的是两个现有的双引号最终出现在最后的扩展行中。也许有一些方法可以逃避引号?

标签: c gcc macros


【解决方案1】:
#define S(x) #x
#define SX(x) S(x)

#define VIOTA(A0) asm(".byte " SX(PRE) ", " SX(A0))

在此处查看详细信息:C Preprocessor, Stringify the result of a macro

【讨论】:

  • 你能解释一下为什么简单的 S(PRE) 不起作用吗? (我测试过,我知道不会)
  • sigh 点击链接。
【解决方案2】:

使用字符串化运算符# 将标记转换为字符串。但是,由于字符串化操作符只能应用于宏参数,所以需要额外添加一些宏层:

#define PRE 0xF1

#define SR0 0B0000
#define SR1 0B0001
#define SR2 0B0010
#define SR3 0B0011

#define VIOTA(A0) VIOTA_HELPER1(PRE, A0)
#define VIOTA_HELPER1(PRE, A0) VIOTA_HELPER2(PRE, A0)
#define VIOTA_HELPER2(PRE, A0) asm(".byte" #PRE ", " #A0)

int main(void)
{
  VIOTA(SR1);
  return 0;
}

预处理后,展开为:

int main(void)
{
  asm(".byte " "0xF1" ", " "0B0001");
  return 0;
}

字符串常量在编译时被连接起来,所以这相当于asm(".byte 0xF1, 0B0001");

【讨论】:

  • 字符串常量是由预处理器连接起来的,我想过吗?
  • C++11 2.14.5/13 说它在翻译阶段 6 中完成。这是我告诉的。
  • @Lightness:如果您想学究气,那么实际上并没有单独的“预处理器”和“编译器”,而是具有多个翻译阶段的单个“翻译器”。对于 C 代码,C99 §5.1.1.2 将字符串文字连接置于第 8 阶段的第 6 阶段,而对于 C++ 代码,C++03 §2.1 将其置于第 9 阶段的第 6 阶段(我手边没有 C++11 的副本) .如果您只运行预处理器(-E 参数)而不进行编译,则 GCC 和 Clang 都不会连接字符串文字。
  • @AdamRosenfield: 在我看来,C++11 2.2/4 是特别明确的(它从Preprocessing directives are executed 开始,然后继续列出预处理器所做的事情,不多不少),将第 4 阶段称为“预处理阶段”。
【解决方案3】:

您正在使传递给 asm() 的字符串成为 PRE 的一部分。字符串中的宏不展开。

这似乎对我有用:

  #define PRE 0xF1

  #define SR0 0B0000
  #define SR1 0B0001
  #define SR2 0B0010
  #define SR3 0B0011

  #define str(s) #s
  #define VIOTA(PRE, A0)  asm( ".byte " str(PRE) ", " str(A0) )

  int main()
  {    
       VIOTA(PRE, SR1);
         return 0;
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 2022-07-06
    相关资源
    最近更新 更多