2011-10-17 21 views
9

Chciałbym ocenić token zanim zostanie on połączony z czymś innym. „Problem” jest to, że norma określa zachowanie jakoOcena tokena preprocesora przed ## concatenation

zanim lista zostanie ponownie zbadana wymiana wiecej nazwy makr do zastąpić każde wystąpienie tokena ## przeróbki na liście wymiana (nie z argumentu) zostaje usunięty, a poprzedzający token preprocesingu jest łączony z następującym tokenem przetwarzania wstępnego.

więc w poniższym przykładzie

#include <stdlib.h> 

struct xy { 
    int x; 
    int y; 
}; 

struct something { 
    char * s; 
    void *ptr; 
    int size; 
    struct xy *xys; 
}; 
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 

#define DECLARE_XY_BEGIN(prefix) \ 
struct xy prefix ## _xy_table[] = { 

#define XY(x, y) {x, y}, 

#define DECLARE_XY_END(prefix) \ 
    {0, 0} \ 
}; \ 
struct something prefix ## _something = { \ 
    "", NULL, \ 
    ARRAY_SIZE(prefix ## _xy_table), \ 
    &(prefix ## _xy_table)[0], \ 
}; 

DECLARE_XY_BEGIN(linear1) 
    XY(0, 0) 
    XY(1, 1) 
    XY(2, 2) 
    XY(3, 3) 
DECLARE_XY_END(linear1) 


#define DECLARE_XY_BEGIN_V2() \ 
struct xy MYPREFIX ## _xy_table[] = { 

#define DECLARE_XY_END_V2() \ 
    {0, 0} \ 
}; \ 
struct something MYPREFIX ## _something = { \ 
    "", NULL, \ 
    ARRAY_SIZE(MYPREFIX ## _xy_table), \ 
    &(MYPREFIX ## _xy_table)[0], \ 
}; 

#define MYPREFIX linear2 
DECLARE_XY_BEGIN_V2() 
    XY(0, 0) 
    XY(2, 1) 
    XY(4, 2) 
    XY(6, 3) 
DECLARE_XY_END_V2() 
#undef MYPREFIX 

Ostatnia deklaracja rozpręża się

struct xy MYPREFIX_xy_table[] = { 
{0, 0}, 
{2, 1}, 
{4, 2}, 
{6, 3}, 
{0, 0} }; struct something MYPREFIX_something = { "", 0, (sizeof(MYPREFIX_xy_table)/sizeof((MYPREFIX_xy_table)[0])), &(MYPREFIX_xy_table)[0], }; 

i nie

struct xy linear2_xy_table[] = { 
{0, 0}, 
{2, 1}, 
{4, 2}, 
{6, 3}, 
{0, 0} }; struct something linear2_something = { "", 0, (sizeof(linear2_xy_table)/sizeof((linear2_xy_table)[0])), &(linear2_xy_table)[0], }; 

jak chcę. Czy istnieje sposób definiowania makr, które to powodują? Pierwszy zestaw makr działa, ale chciałbym uniknąć duplikacji prefiksu i zdefiniować to tylko raz. Czy możliwe jest ustawienie prefiksu za pomocą #define i zezwolić na użycie makr?

+0

możliwe duplikat [Jak złączyć dwa razy z C preprocesora i poszerzyć makro jak w „arg ## \ _ # # MACRO "?] (Http://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-c-preprocessor-and-expand-a-mac-as-in-arg) Proszę spróbować aby zminimalizować przykłady :-) –

Odpowiedz

4

Do tego celu można użyć rozszerzenia drugiego poziomu, np.

#define XY_HLP1(a) DECLARE_XY_BEGIN(a) 
#define XY_HLP2(a) DECLARE_XY_END(a) 
#define DECLARE_XY_BEGIN_V2() XY_HLP1(MYPREFIX) 
#define DECLARE_XY_END_V2() XY_HLP2(MYPREFIX) 
+0

Tak, podoba mi się to. Nie trzeba zmieniać starych makr i tworzyć ewentualnych problemów z łączeniem dla innych, a nawet jeśli podwójne rozszerzenie może nie być intuicyjne, aby zrozumieć, że nadal jest oczywiste, że ten sam prefiks jest używany w obu miejscach. – hlovdal

11

You can use a macro for concatenation jak

#define CONCAT_(A, B) A ## B 
#define CONCAT(A, B) CONCAT_(A, B) 

to działa wtedy

#define A One 
#define B Two 
CONCAT(A, B) // Results in: OneTwo 
+1

Nigdy nie rozumiałem, dlaczego takie rzeczy wymagają dwóch poziomów. Czy jest to pierwszy poziom do ekspansji makr, a drugi do faktycznej konkatenacji? – ijustlovemath