2010-04-16 15 views
20

Bir sorunla karşılaştım - Hem dize hem de tam sayı olarak bir makro değeri kullanmam gerekiyor.Makro değerinin tanımlanması

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

Bu "başıboş #" bir mesajla başarısız ve işe yaradı bile, ben makro isimleri, değerleri değil dizgelenmiş yerdik. Tabii ki değerleri son yöntemle ("LIMIT %d ", page*RECORDS_PER_PAGE) besleyebilirim ama ne güzel ne de verimli. Önişlemcinin dizeleri özel bir şekilde işlemesini ve içeriğinin normal kod gibi işlenmesini istediğim zamanlar böyle oluyor. Şimdilik, #define RECORDS_PER_PAGE_TXT "10" ile kundaklamadım ama anlaşılabilir bir şekilde, bundan memnun değilim.

Nasıl edinilir?

+2

Gcc'de benim için önceden doğru şekilde işlendi. – kennytm

+0

Linux çekirdeği ile ilgili örnek: http://lxr.free-electrons.com/source/include/linux/stringify.h?v=4.7 –

cevap

37

#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

bu yeni bir gereklilik midir? En son d codeification kullanmam için böyle numaralar gerektiğini hatırlamıyorum ... – PypeBros

+0

Daha fazla referans için, http://gcc.gnu.org/onlinedocs adresinden erişilebilen dizinin (GNU CPP) mekaniğinin (ve nüansının) ek açıklaması /cpp/Stringification.html. –

+1

Güncelleme GCC doc bağlantısı: https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing – eresonance

2

çift

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

benim için derler senin tırnak kaçan deneyin. RECORDS_PER_PAGE belirteci, ESCAPEQUOTE makro çağrısı ile genişletilecek ve ardından DOUBLEESCAPE'a gönderilecektir.

+0

Ancak, doğru değerleri almaz çünkü # içeriği içeriği önce değerlendirilmez . –

+0

@Mike Çifte kaçmayı unuttum –

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

Çıkışlar:

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

Not indirection onları stringifying önce argümanları değerlendirmek _REQUEST_RECORDS için. Aşağıda tanımlanan xstr makrosu, makro genişletme yaptıktan sonra dizgeye girecektir.