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
Stringification of a macro value
提问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被引用。

