2010-04-16 33 views
20

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

#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... */ 

这失败,一个关于“流浪#”消息,即使它的工作,我想我会得到的宏名字符串化,而不是值。当然,我可以将这些值填入最终方法("LIMIT %d ", page*RECORDS_PER_PAGE),但它既不美观也不有效。 当我希望预处理器没有以特殊方式处理字符串,并且像处理普通代码一样处理它们的内容时,就像这样。 现在,我用#define RECORDS_PER_PAGE_TXT "10"来搪塞它,但可以理解的是,我对此并不满意。

如何解决此问题?

+2

在gcc上为我正确预处理。 – kennytm 2010-04-16 13:29:14

+0

Linux内核示例:http://lxr.free-electrons.com/source/include/linux/stringify.h?v=4.7 – 2016-11-03 17:10:51

回答

37

下面定义的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) ";" 
+1

这是最近的一项要求吗?我不记得上次我使用字符串化时需要使用这种技巧... – PypeBros 2012-12-07 10:37:06

+0

有关更多参考资料,请参阅http://gcc.gnu.org/onlinedocs上关于字符串化(GNU CPP)的机制(和细微差别)的其他描述/cpp/Stringification.html。 – 2014-05-27 16:12:01

+1

更新的GCC文档链接:https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing – eresonance 2017-02-27 20:17:14

2

尽量逃避双引号的

#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; 
} 

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

+0

但是它并没有替代正确的值,因为#的内容不是先评估。 – 2010-04-16 13:40:36

+0

@Mike忘记双逃逸 – 2010-04-16 13:45:02

1
#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; 
} 

输出:

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

注意间接的方式_REQUEST_RECORDS字符串化之前评估的参数。