代码之家  ›  专栏  ›  技术社区  ›  roschach

C宏字符串化变量

  •  1
  • roschach  · 技术社区  · 6 年前

    例如,代码取自 this post

    #define MAX_STRING_LENGTH 20
    #define STRINGIFY(x) STRINGIFY2(x)
    #define STRINGIFY2(x) #x
    
    {
      ...
      char word[MAX_STRING_LENGTH+1];     
      scanf("%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
      ...
    }
    

    但是,我不能将其与以下变量一起使用:

    {
      ...
      int val = 20;
      char word[MAX_STRING_LENGTH+1];     
      scanf("%" STRINGIFY(val) "s", word);
      ...
    }
    

    由于编译成功并出现此警告:

    warning: invalid conversion specifier 'v' [-Wformat-invalid-specifier]
        scanf("%" STRINGIFY(var) "s", word);
               ~~~^~~~~~~~~~~~~
    test2.c:4:22: note: expanded from macro 'STRINGIFY'
    #define STRINGIFY(x) STRINGIFY2(x)
                         ^
    test2.c:5:23: note: expanded from macro 'STRINGIFY2'
    #define STRINGIFY2(x) #x
                          ^
    <scratch space>:466:2: note: expanded from here
    "var"
     ^
    1 warning generated
    

    但是代码的运行并不等待任何输入。

    this other post 可以将变量传递到此宏:

    #define PRINT(int) printf(#int "%d\n",int)
    ...
    int var =8;
    PRINT(var);
    

    这两种情况有什么区别?如何修改第一个,使其也接受变量?

    %d 在宏内部,但我没有成功。

    2 回复  |  直到 6 年前
        1
  •  5
  •   StoryTeller - Unslander Monica    6 年前

    预处理器始终仅对令牌进行操作。

    STRINGIFY(MAX_STRING_LENGTH) 令牌序列是 MAX_STRING_LENGTH ,及 STRINGIFY(val) 这是令牌序列 val .

    最大字符串长度 它本身就是一个宏,又是如何产生的呢 STRINGIFY 如果定义为工作,则在将宏转换为字符串文字之前,预处理器将展开宏。所以 20 依次是获得的令牌 # 应用于它,它就会产生 "20" 作为字符串文本。

    瓦尔 瓦尔 . 事实 瓦尔 没有什么 瓦尔 被转换为文字 "val" .

    您从另一篇文章中带来的示例之所以有效,是因为它扩展到以下内容:

    printf("var" "%d\n", var);
    

    #int 转换为文本时,没有让预处理器读取变量值的魔法。事实 var 8 var printf ! 它在运行时由 %d

    最后,在使用预处理器进行实验时,在预处理完成后,但在编译文件之前查看源文件总是很有帮助的。这个 gcc -E 标志(或编译器的等效标志)可以帮助您做到这一点。

        2
  •  3
  •   Aconcagua    6 年前

    STRINGIFY(val) "val" ,而不是您想要字符串化的值,因此您将得到字符串的最终格式 "%vals" "%" "val" "s"

    这个 PRINT 例子:

    #define PRINT(int) printf(#int "%d\n", int)
    
    PRINT(var);                // to be resolved
    printf(#var  "%d\n", var); // intermediate result
    printf("var" "%d\n", var); // final result, this is what the C compiler sees
    

    MAX_STRING_LENGTH ?

    #define MAX_STRING_LENGTH 20
    #define STRINGIFY(x) STRINGIFY2(x)
    #define STRINGIFY2(x) #x
    
    STRINGIFY(MAX_STRING_LENGTH)  // to be resolved
    STRINGIFY2(20)                // intermediate step; STRINGIFY2 known as macro, thus:
    #20                           // another intermediate step
    "20"                          // final result