Estreitamento de um valor de macro

Eu enfrentei um problema – eu preciso usar um valor de macro como string e como inteiro.

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

Isso falha com uma mensagem sobre “stray #” e, mesmo que funcionasse, eu acho que teria os nomes de macro esticados, não os valores. É claro que posso alimentar os valores para o método final ( "LIMIT %d ", page*RECORDS_PER_PAGE ), mas não é bonito nem eficiente. É hora desse quando eu gostaria que o pré-processador não tratasse as strings de uma maneira especial e processasse seu conteúdo como o código normal. Por enquanto, eu o limpei com #define RECORDS_PER_PAGE_TXT "10" mas compreensivelmente, não estou feliz com isso.

Como acertar?

    A macro xstr definida abaixo será estendida depois de fazer a macroexpansão.

     #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) ";" 
     #include  #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; } 

    Saídas:

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

    Observe a indirecção para _REQUEST_RECORDS para avaliar os argumentos antes de os restringir.

    Tente o dobro de escaping suas citações

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

    compila para mim. O token RECORDS_PER_PAGE será expandido pela chamada de macro ESCAPEQUOTE , que é então enviada para DOUBLEESCAPE para ser citada.