2009-08-17 37 views
5

Có thể xác định macro C/C++ "BUILD(a, i)" mở rộng thành "x[0], x[1], x[2], ..., x[i]" không? Giống như trongMở rộng đệ quy macro thành một chuỗi

#define BUILD(x, 0) x[0] 
#define BUILD(x, 1) x[0], x[1] 
#define BUILD(x, 2) x[0], x[1], x[2] 
... 

Có vẻ như BOOST_PP_ENUM_PARAMS có thể thực hiện công việc. Tôi cho rằng tôi chỉ có thể #include tăng, nhưng tôi quan tâm đến việc biết làm thế nào và tại sao nó hoạt động, bất cứ ai có thể giải thích?

Tôi muốn gọi một hàm f(int, ...) mà mất N int luận x[i], 0 < = i < N. Trong đó N được biết đến là ceil(sizeof(A)/sizeof(B)). Thật không may, tôi không thể sử dụng varargs hoặc mẫu.

+0

liên quan: http://stackoverflow.com/questions/824639/variadic-recursive-preprocessor-macros-is-it-possible/893684 –

+0

vấn đề gì được bạn thực sự cố gắng để giải quyết? I E. kết quả của macro này sẽ được sử dụng để làm gì? Việc sử dụng có thể được thay đổi một chút để cho phép một giải pháp mẫu (nơi đệ quy có thể)? –

+0

Xem chỉnh sửa cuối cùng của tôi. –

Trả lời

14

Có thể, nhưng bạn phải thực hiện một số công việc thủ công và có giới hạn trên.

#define BUILD0(x) x[0] 
#define BUILD1(x) BUILD0(x), x[1] 
#define BUILD2(x) BUILD1(x), x[2] 
#define BUILD3(x) BUILD2(x), x[3] 
#define BUILD(x, i) BUILD##i(x) 

Và lưu ý rằng i phải là số nguyên, không phải là giá trị được tính hằng số.

BTW, bộ tiền xử lý mạnh hơn so với thông thường, nhưng việc sử dụng sức mạnh đó khá phức tạp. Boost cung cấp một thư viện giúp giảm bớt một số thứ, bao gồm cả lặp lại. Xem Boost Preprocessor Library. Có một thư viện khác cho những thứ như vậy, nhưng tên của nó đã trốn thoát tôi vào lúc này.

Chỉnh sửa: Thư viện tiền xử lý tăng cường sử dụng kỹ thuật tương tự. Với các thủ thuật bổ sung để giải quyết một số vấn đề về góc, chia sẻ các macro triển khai giữa các cơ sở cấp cao hơn, làm việc xung quanh các lỗi trình biên dịch, v.v ... mức độ phức tạp tăng bình thường là điều bình thường trong bối cảnh của một thư viện đa mục đích. các nguyên tắc thực hiện. Có lẽ thủ thuật đáng chú ý nhất là thêm một mức độ gián tiếp để nếu tham số thứ hai có thể là một macro, nó được mở rộng. I E. với

#define BUILD_(x, i) BUILD##i(x) 
#define BUILD(x, i) BUILD_(x, i) 

ai có thể thực hiện cuộc gọi

#define FOO 42 
BUILD(x, FOO) 

đó là không thể với những gì tôi tiếp xúc.

+0

Cảm ơn, thú vị của nó như thế nào BUILD1..BUILD3 là gần như giống nhau ... tôi không thể có một cái gì đó như #define BUILD_ (x, j) BUILD_ (x, j-1), x [j] –

+0

Nó sẽ không có điều kiện dừng và macro không thể đệ quy để khởi động. – Blindy

+0

+1 để có giải thích tốt đẹp! –

2

Không, không phải - macro không thể đệ quy. Và các macro bạn đăng không phải là variadic, có nghĩa là "có số lượng tham số khác nhau".

+1

Cảm ơn, tôi đã xóa thẻ variadic. –

0

Ok, Tôi đã có cùng một vấn đề, Mục đích của tôi là in tất cả các giá trị của một mảng N byte bằng cách sử dụng macro. Tôi cho rằng bạn có khá nhiều vấn đề tương tự. Nếu đây là trường hợp, giải pháp này phải phù hợp với các vấn đề tương tự trong tương lai.

#define HEX_ARRAY_AS_STR(array, len) \ 
    ({ \ 
     int print_counter = 0; \ 
     print_buf = calloc(len*3+1, 1); \ 
     char *tmp_print_buf = print_buf; \ 
     uint8_t *array_flower = array; \ 
     while(print_counter++ < (len)){ \ 
      sprintf(tmp_print_buf, "%02X ", *(array_flower)++); \ 
      tmp_print_buf += 3; \ 
     } \ 
     print_buf; \ 
    }) 

#define eprintf(...) \ 
    do{ \ 
     char *print_buf; \ 
     printf(__VA_ARGS__); \ 
     if(print_buf) \ 
      free(print_buf); \ 
    }while(0) 

int 
main(int argc, char *argv[]) 
{ 
    uint8_t sample[] = {0,1,2,3,4,5,6,7}; 
    eprintf("%s\n", HEX_ARRAY_AS_STR(sample, 8)); 
    return 0; 
} 
+0

Không, đây không phải là những gì tôi đang cố gắng làm. Dù sao, nếu bạn luôn chuyển một mảng tới HEX_ARRAY_AS_STR, bạn có thể loại bỏ tham số thứ hai bằng cách sử dụng sizeof (mảng)/sizeof (uint8_t) –

Các vấn đề liên quan