字符串中的GCC宏扩展参数

字符串中的GCC宏扩展参数,c,gcc,macros,C,Gcc,Macros,我有这样的情况 #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(“字节0xF1

我有这样的情况

#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(“字节0xF1,0B0000”)


在这里,内部宏已展开。我真的一点也不确定我做错了什么。有什么建议吗?

您正在制作传递给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;
  }

请参见此处的详细信息:

使用字符串化操作符
#
将令牌转换为字符串。但是,由于字符串化操作符只能应用于宏参数,因此需要添加一些额外的宏层:

#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,0b001”)

附加一点信息。是的,这里的报价是个问题,但重要的是,两个现有的双引号最终会出现在最终的扩展行中。也许有什么方法可以避开引号?我想可能是字符串常量的重复被预处理器连接起来了?C++11 2.14.5/13说它是在翻译阶段6完成的。这是我说的。@Lightness:如果你想学究气,那么实际上没有一个单独的“预处理器”和“编译器”,而是一个具有多个翻译阶段的“翻译器”。C99的5.5.1.2将C字串连接在C代码的8的第6阶段中,而C++ 03的2.1将它放在C++的9的阶段6中(我没有一个c++ 11的拷贝)。如果只运行预处理器(参数
-E
),而不进行编译,则GCC和Clang都不会连接字符串文本。@AdamRosenfield:C++11 2.2/4在我看来是明确的(它开始执行
预处理指令
,并继续列出预处理器所做的事情,不多不少),把第四阶段称为“预处理阶段”。你能解释一下为什么简单的S(PRE)不起作用吗?(我已经测试过了,我知道没有)点击链接。
int main(void)
{
  asm(".byte " "0xF1" ", " "0B0001");
  return 0;
}