C语言 宏值的字符串化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2653214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:11:27  来源:igfitidea点击:

Stringification of a macro value

cstringconcatenationc-preprocessor

提问by SF.

I faced a problem - I need to use a macro value both as string and as integer.

我遇到了一个问题 - 我需要使用一个宏值作为字符串和整数。

 #define RECORDS_PER_PAGE 10

 /*... */

 #define REQUEST_RECORDS \
      "SELECT Fields FROM Table WHERE Conditions" \
      " OFFSET %d * " #RECORDS_PER_PAGE \
      " LIMIT " #RECORDS_PER_PAGE ";"

 char result_buffer[RECORDS_PER_PAGE][MAX_RECORD_LEN];

 /* ...and some more uses of RECORDS_PER_PAGE, elsewhere... */

This fails with a message about "stray #", and even if it worked, I guess I'd get the macro names stringified, not the values. Of course I can feed the values to the final method ( "LIMIT %d ", page*RECORDS_PER_PAGE) but it's neither pretty nor efficient. It's times like this when I wish the preprocessor didn't treat strings in a special way and would process their content just like normal code. For now, I cludged it with #define RECORDS_PER_PAGE_TXT "10"but understandably, I'm not happy about it.

这会失败并显示有关“stray #”的消息,即使它有效,我想我也会将宏名称字符串化,而不是值。当然,我可以将值提供给最终方法 ( "LIMIT %d ", page*RECORDS_PER_PAGE) 但它既不美观也不高效。在这种情况下,我希望预处理器不要以特殊方式处理字符串,而是像处理普通代码一样处理它们的内容。现在,我坚持了下来,#define RECORDS_PER_PAGE_TXT "10"但可以理解的是,我对此并不满意。

How to get it right?

如何做对?

回答by Matthew T. Staebler

The xstrmacro defined below will stringify after doing macro-expansion.

下面xstr定义的宏将在进行宏扩展后进行字符串化。

#define xstr(a) str(a)
#define str(a) #a

#define RECORDS_PER_PAGE 10

#define REQUEST_RECORDS \
    "SELECT Fields FROM Table WHERE Conditions" \
    " OFFSET %d * " xstr(RECORDS_PER_PAGE) \
    " LIMIT " xstr(RECORDS_PER_PAGE) ";"

回答by Mike Weller

#include <stdio.h>

#define RECORDS_PER_PAGE 10

#define TEXTIFY(A) #A

#define _REQUEST_RECORDS(OFFSET, LIMIT)                 \
        "SELECT Fields FROM Table WHERE Conditions"     \
        " OFFSET %d * " TEXTIFY(OFFSET)                 \
        " LIMIT " TEXTIFY(LIMIT) ";"

#define REQUEST_RECORDS _REQUEST_RECORDS(RECORDS_PER_PAGE, RECORDS_PER_PAGE)

int main() {
        printf("%s\n", REQUEST_RECORDS);
        return 0;
}

Outputs:

输出:

SELECT Fields FROM Table WHERE Conditions OFFSET %d * 10 LIMIT 10;

Note the indirection to _REQUEST_RECORDS to evaluate the arguments before stringifying them.

请注意 _REQUEST_RECORDS 的间接性,以在对参数进行字符串化之前对其进行评估。

回答by Scott Wales

Try double escaping your quotes

尝试双重转义您的报价

#define RECORDS_PER_PAGE 10
#define MAX_RECORD_LEN 10

 /*... */
#define DOUBLEESCAPE(a) #a
#define ESCAPEQUOTE(a) DOUBLEESCAPE(a)
#define REQUEST_RECORDS \
      "SELECT Fields FROM Table WHERE Conditions" \
      " OFFSET %d * " ESCAPEQUOTE(RECORDS_PER_PAGE)       \
      " LIMIT " ESCAPEQUOTE(RECORDS_PER_PAGE) ";"

 char result_buffer[RECORDS_PER_PAGE][MAX_RECORD_LEN];

int main(){
  char * a = REQUEST_RECORDS;
}

compiles for me. The token RECORDS_PER_PAGEwill be expanded by the ESCAPEQUOTEmacro call, which is then sent into DOUBLEESCAPEto be quoted.

为我编译。令牌RECORDS_PER_PAGE将被ESCAPEQUOTE宏调用扩展,然后被发送到DOUBLEESCAPE被引用。