2010-04-16 83 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字符串化之前評估的參數。