Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 宏值的字符串化_C_String_Concatenation_C Preprocessor - Fatal编程技术网

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) ";"