【问题标题】:Macro stringifies a previous macros identifier instead of its replacement [duplicate]宏将先前的宏标识符字符串化而不是其替换[重复]
【发布时间】:2017-02-07 22:39:09
【问题描述】:

为什么inner_LOAD_ATOM(buffer, ATOM_MAX) 被转换为scanf("%" "ATOM_MAX" "s", x) 但包装后的版本没有?我希望 ATOM_MAX(identifier) 在“传递”给inner_LOAD_ATOMLOAD_LINE 之前被 10 替换,并使包装器无用。非常感谢更详细的回答为什么需要包装器。

#include <stdio.h>

#define ATOM_MAX 10
#define inner_LOAD_ATOM(x, y) scanf("%" #y "s", x)      /* inner part */
#define LOAD_ATOM(x, y) inner_LOAD_ATOM(x, y)           /* wrapper of inner_LOAD_ATOM */


int main(void)
{
    char buffer[ATOM_MAX] = {0, };

    /* wrapped works fine */
    LOAD_ATOM(buffer, ATOM_MAX);        

    /* [Warning] unknown conversion
    type character 'A' in format [-Wformat=] */
    inner_LOAD_ATOM(buffer, ATOM_MAX);

    printf("%s\n", buffer);


    return 0;
}

【问题讨论】:

    标签: c macros stringification


    【解决方案1】:

    了解类函数宏的工作方式与 C 函数不同,这一点很重要。 (几乎)没有宏调用堆栈或将参数从一个宏转发到另一个宏的感觉。相反,宏扩展迭代进行——宏被其扩展替换,然后重新扫描扩展以寻找更多宏来扩展。

    类似函数的宏的参数在插入到宏的替换文本之前被完全宏扩展,除了,它们是字符串化 (#) 或标记粘贴 (@987654322) 的操作数@) 操作员。因此,如果直接调用inner_LOAD_ATOM(buffer, ATOM_MAX),则ATOM_MAX在应用#运算符之前不会展开。

    另一方面,当您调用 LOAD_ATOM(buffer, ATOM_MAX) 时,ATOM_MAX 宏在 LOAD_ATOM() 展开之前展开。 inner_LOAD_ATOM() 在这一点上没有考虑在内 - 它只是外部宏替换文本的一部分,直到重新扫描 LOAD_ATOM() 的扩展以进行进一步的宏扩展。

    【讨论】:

      【解决方案2】:

      因为在第一遍#y 将被#ATOM_MAX 替换并字符串化。所以它不会在第二遍时扩展。让我们手动运行它:

      第一关:

      int main(void)
      {
          char buffer[10] = {0, };
      
          /* wrapped works fine */
          inner_LOAD_ATOM(buffer, 10); // <-- Note - here it ATOM_MAX was expanded in the first pass       
      
          /* [Warning] unknown conversion
          type character 'A' in format [-Wformat=] */
          scanf("%" "ATOM_MAX" "s", buffer); 
      
          printf("%s\n", buffer);
      
      
          return 0;
      }
      

      第二遍:

      int main(void)
      {
          char buffer[10] = {0, };
      
          /* wrapped works fine */
          scanf("%" "10" "s", buffer);        
      
          /* [Warning] unknown conversion
          type character 'A' in format [-Wformat=] */
          scanf("%" "ATOM_MAX" "s", buffer);   // <----- Not expanded as is interpreted as string
      
          printf("%s\n", buffer);
      
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-21
        • 2018-02-05
        • 2015-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多