2008-11-19 15 views
25

Tôi muốn làm tương đương với các nội dung sau:Có thể cho các macro tiền xử lý C chứa các chỉ thị tiền xử lý không?

#define print_max(TYPE) \ 
# ifdef TYPE##_MAX \ 
    printf("%lld\n", TYPE##_MAX); \ 
# endif 

print_max(INT); 

Bây giờ #ifdef hoặc bất kỳ chỉ thị tiền xử lý lồng nhau được không được phép như xa như tôi có thể nhìn thấy trong một chức năng vĩ mô. Bất kỳ ý tưởng nào?

Cập nhật: Vì vậy, có vẻ như điều này là không thể. Ngay cả một hack để kiểm tra tại thời gian chạy có vẻ không thể thực hiện. Vì vậy, tôi nghĩ rằng tôi sẽ đi với một cái gì đó như:

#ifndef BLAH_MAX 
# define BLAH_MAX 0 
#endif 
# etc... for each type I'm interested in 

#define print_max(TYPE) \ 
    if (TYPE##_MAX) \ 
     printf("%lld\n", TYPE##_MAX); 

print_max(INT); 
print_max(BLAH); 

Trả lời

0

Tôi không nghĩ rằng đó là trường hợp của toán tử ## không được phép trong #ifdef. Tôi đã thử điều này:

#define _print_max(TYPE) \ 
#ifdef TYPE \ 
printf("%lld\n", _TYPE); \ 
#endif 

#define print_max(TYPE) _print_max(MAX##_TYPE) 


void main() 
{ 
    print_max(INT) 
} 

và vẫn không hoạt động (không giống như #ifdef TYPE). Vấn đề là #ifdef sẽ chỉ chấp nhận các ký hiệu #defined, không phải #define arguments. Đó là hai việc khác nhau.

4

Tôi đã thử điều đó trước đây. Vấn đề là # đã được dành riêng để stringize một tham số macro. Nó không được phân tích cú pháp như một mã thông báo tiền xử lý giống như mã thông báo # xác định.

0

Không giống như mẫu, bộ tiền xử lý không phải là turing-complete. An #ifdef bên trong macro là không thể. Giải pháp duy nhất của bạn là đảm bảo rằng bạn chỉ gọi print_max trên các loại có một số _MAX phù hợp được xác định, ví dụ: INT_MAX. Trình biên dịch chắc chắn sẽ cho bạn biết khi nào không.

2

Giải pháp duy nhất tôi có là gian lận - tạo danh sách các loại có _XXX_MAX làm bộ định nghĩa và sau đó sử dụng. Tôi không biết làm thế nào để tạo ra danh sách trong thời trang tự động trong preprocessor, vì vậy tôi không cố gắng. Giả định là danh sách không quá dài và sẽ không được duy trì quá sâu.

#define PRINT_MAX(type) printf("%lld\n", _TYPE##_MAX); 
#define HAVE_MAX(type) _TYPE##_MAX // not sure if this works 


/* a repetitious block of code that I cannot factor out - this is the cheat */ 
#ifdef HAVE_MAX(INT) 
#define PRINT_INT_MAX PRINT_MAX(INT) 
#endif 

#ifdef HAVE_MAX(LONG) 
#define PRINT_LONG_MAX PRINT_MAX(LONG) 
#endif 
/* end of cheat */ 


#define print_max(type) PRINT_##TYPE##_MAX 
10

Các Boost Preprocessor (mà làm việc cho C cũng như C++, mặc dù Boost như một toàn thể là một thư viện C++) thư viện có thể giúp loại nhiệm vụ. Thay vì sử dụng #ifdef trong macro (không được phép), nó giúp bạn bao gồm tệp nhiều lần, với các macro khác nhau được xác định mỗi lần để tệp có thể sử dụng #ifdef.

Mã sau, nếu được lưu vào max.c, nên làm những gì bạn muốn cho mỗi từ được liệt kê trong MAXES #define ở đầu tệp. Tuy nhiên, nó sẽ không hoạt động nếu bất kỳ giá trị _MAX nào là dấu phẩy động, vì bộ tiền xử lý không thể xử lý dấu chấm động.

(Boost Processor là một công cụ hữu ích, nhưng nó không hoàn toàn đơn giản, bạn có thể quyết định có hay không phương pháp này là một sự cải tiến so với sao chép và dán.)

#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST) 

#if !BOOST_PP_IS_ITERATING 

/* This portion of the file (from here to #else) is the "main" file */ 

#include <values.h> 
#include <stdio.h> 
#include <boost/preprocessor.hpp> 

/* Define a function print_maxes that iterates over the bottom portion of this 
* file for each word in MAXES */ 
#define BOOST_PP_FILENAME_1 "max.c" 
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES))) 
void print_maxes(void) { 
#include BOOST_PP_ITERATE() 
} 

int main(int argc, char *argv[]) 
{ 
    print_maxes(); 
} 

#else 

/* This portion of the file is evaluated multiple times, with 
* BOOST_PP_ITERATION() resolving to a different number every time */ 

/* Use BOOST_PP_ITERATION() to look up the current word in MAXES */ 
#define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES) 
#define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX) 

#if CURRENT_MAX 
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld\n", (long long) CURRENT_MAX); 
#else 
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined\n"); 
#endif 

#undef CURRENT 
#undef CURRENT_MAX 

#endif 
0

Không có cách nào dễ dàng để làm điều này. Gần nhất bạn có thể đến là # define một số lượng lớn các ifdef macro như:

#undef IFDEF_INT_MAX 
#ifdef INT_MAX 
#define IFDEF_INT_MAX(X) X 
#else 
#define IFDEF_INT_MAX(X) 
#endif 

#undef IFDEF_BLAH_MAX 
#ifdef BLAH_MAX 
#define IFDEF_BLAH_MAX(X) X 
#else 
#define IFDEF_BLAH_MAX(X) 
#endif 

    : 

kể từ khi bạn cần rất nhiều trong số họ (và họ có thể có nhiều nơi hữu ích), nó làm cho rất nhiều ý nghĩa với dính tất cả những thứ này vào tập tin tiêu đề 'ifdefs.h' mà bạn có thể đưa vào bất cứ khi nào bạn cần chúng. Bạn thậm chí có thể viết một kịch bản mà tái tạo ifdef.h từ một danh sách của 'macro quan tâm'

Sau đó, mã của bạn trở nên

#include "ifdefs.h" 
#define print_max(TYPE) \ 
IFDEF_##TYPE##_MAX(printf("%lld\n", TYPE##_MAX);) 

print_max(INT); 
print_max(BLAH);