2012-10-10 13 views
10

Prawdopodobnie naiwne pytanie - programowałem 20 lat temu i od tego czasu nie kodowałem. Moja pamięć o tym, jak C preprocessor Works atrofii znacząco od tego czasu ...Format matrycy dla #define (preprocesor C)

Piszę bardzo prosty C program i próbuję zadeklarować kilka statycznych tablic globalnych, ale wielkość arrays będzie zależny (na niebagatelny sposób) na zmiennej MODE. Coś jak uproszczony przykład poniżej.

Dwa krótkie punkty: Wiem, że mogłem po prostu zmienić rozmiar arrays według największego rozmiaru wymaganego przez dowolny MODE, ale nie chcę tego, ponieważ (inaczej niż w uproszczonym przykładzie poniżej) czasami garść tych wymiarów jest będą bardzo duże, a inne małe.

Ponadto chcę używać statycznie zdefiniowanych globalnych tablic - zamiast dynamicznie alokować je w czasie wykonywania. Chcę, aby kompilator miał rozmiary w czasie kompilacji.

//** Simplified example of what I'd like to do **//  
#define SIZE_LIST_1[5] = {2, 7, 23, 33, 12, 76} // I don't think this is valid syntax 
#define SIZE_LIST_2[5] = {11, 65, 222, 112, 444} 

#define MODE 4 
#define S1 SIZE_LIST_1[MODE] 
#define S2 SIZE_LIST_2[MODE] 

int a[S1], b[S2]; 
+0

'int SIZE_LIST_1 [5] = {2,7 ... 76};' –

+1

Makra są podstawieniami. – Jack

+0

Nie rozumiem, co masz na myśli przez [S1]. co tam próbujesz? –

Odpowiedz

10

Trzeba zdefiniować kilka makr pomocniczych, zanim będzie można to zrobić w prosty sposób:

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

#define ARGN(N, LIST)  EXPAND_CONCAT(ARG_, N) LIST 
#define ARG_0(A0, ...)  A0 
#define ARG_1(A0, A1, ...) A1 
#define ARG_2(A0, A1, A2, ...)  A2 
#define ARG_3(A0, A1, A2, A3, ...) A3 
#define ARG_4(A0, A1, A2, A3, A4, ...)  A4 
#define ARG_5(A0, A1, A2, A3, A4, A5, ...) A5 
#define ARG_6(A0, A1, A2, A3, A4, A5, A6, ...)  A6 
#define ARG_7(A0, A1, A2, A3, A4, A5, A6, A7, ...) A7 
#define ARG_8(A0, A1, A2, A3, A4, A5, A6, A7, A8, ...)  A8 
#define ARG_9(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, ...) A9 
#define ARG_10(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10 

/* above should be in a pp_helper.h header file or some such */ 

#define SIZE_LIST_1 (2, 7, 23, 33, 12, 76) 
#define SIZE_LIST_2 (11, 65, 222, 112, 444, 1000) 

#define S1 ARGN(MODE, SIZE_LIST_1) 
#define S2 ARGN(MODE, SIZE_LIST_2) 

#define MODE 4 

int a[S1], b[S2]; 

Istnieje grono "Biblioteki preprocesora", które można uzyskać za pomocą kodu standardowego (zwiększenie PP, P99), lub po prostu przetasować własne. Głównym problemem jest to, że musisz zdefiniować makra ARG na podstawie największej liczby argumentów, z którymi kiedykolwiek będziesz chciał sobie poradzić.

7

Prawdopodobnie najlepiej można zrobić coś takiego:

#define SIZE_LIST_1_0 2 
#define SIZE_LIST_1_1 7 
#define SIZE_LIST_1_2 23 
#define SIZE_LIST_1_3 33 
#define SIZE_LIST_1_4 12 

#define SIZE_LIST_2_0 11 
#define SIZE_LIST_2_1 65 
#define SIZE_LIST_2_2 222 
#define SIZE_LIST_2_3 112 
#define SIZE_LIST_2_4 444 

#define MODE 4 

#define S1 SIZE_LIST_1_##MODE 
#define S2 SIZE_LIST_2_##MODE 

int a[S1], b[S2]; 
+0

Dziękuję Paul - to trochę bałagan, ale może rozwiązać problem. Nie wiedziałem, że możesz to zrobić. Uważam, że nie ma "bardziej eleganckiego" sposobu na zrobienie tego? – user1735592

+0

Nie - preprocesor jest naprawdę bardzo ograniczony i nie był przeznaczony do tego rodzaju nadużycia. Nie wiem, dlaczego ta odpowiedź uzyskała anonimowy głos w dół - nie jest zbyt elegancka, ale rozwiązuje problem. No cóż ... –

+1

Nie widzę też powodu, dla którego miałby on zostać odrzucony. Jeszcze raz dziękuję za pomysł. – user1735592

3

Obawiam się, że nie ma takiej możliwości.

Proponuję następujące podejście zamiast:

#define MODE 0 

#define DECLARE_ARRAYS_WITH_SIZES(S1, S2, S3) \ 
    int arr1[S1]; \ 
    int arr2[S2]; \ 
    int arr3[S3]; 

#if MODE == 0 
DECLARE_ARRAYS_WITH_SIZES(3, 6, 7) 
#elif MODE == 1 
DECLARE_ARRAYS_WITH_SIZES(8, 2, 1) 
#endif