C 宏值的字符串化
我遇到了一个问题-我需要将宏值同时用作字符串和整数C 宏值的字符串化,c,string,concatenation,c-preprocessor,C,String,Concatenation,C Preprocessor,我遇到了一个问题-我需要将宏值同时用作字符串和整数 #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[REC
#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... */
这失败了,因为出现了一条关于“trasset#”的消息,即使它起作用,我想我还是会将宏名称字符串化,而不是将值字符串化。当然,我可以将这些值提供给最终的方法(“LIMIT%d”,page*每页记录),但它既不美观也不高效。
在这种情况下,我希望预处理器不要以特殊的方式处理字符串,并像处理普通代码一样处理它们的内容。
现在,我把它与#define RECORDS_PER_PAGE_TXT“10”
混为一谈,但可以理解,我对此并不满意
如何使其正确?尝试双重转义您的引号
#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;
}
为我编译。每个页面的令牌记录将由escapekote
宏调用展开,然后将宏调用发送到DOUBLEESCAPE
中引用
#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;
}
请注意,在字符串化参数之前,间接请求记录评估参数。下面定义的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) ";"
在gcc上对我进行了正确的预处理。Linux内核上的示例:我会重新考虑其中的“%d”
,只考虑一般原则上的查询变量<代码>%d“
不太可能容易受到注入攻击,但这似乎是一个坏习惯。但它不能替换正确的值,因为没有首先计算#的内容。@Mike忘记了双转义符这是最近的要求吗?我不记得上次我使用字符串化时需要这些技巧……为了进一步参考,可以在以下网址获得关于字符串化(GNU CPP)机制(和细微差别)的附加说明。更新的GCC文档链接:此文档引用向我解释:“无法将参数与周围的文本组合在一起并将其字符串化。相反,您可以编写一系列相邻的字符串常量和字符串化参数。
“@VictorSergienko:这不是什么新鲜事,也没有什么害处-字符串文字连接,char*abc=“a”“B”“C”
在所有方面都等同于char*abc=“abc”
这里的技巧是如何获得字符串化的等价物,”B“
而不是'B'
或B
。
#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) ";"