2010-11-08 34 views
11

thể trùng lặp:
Can I redefine a C++ macro then define it back?Bảo tồn tiền xử lý các định nghĩa

Nói rằng tôi có một số mã có sử dụng tên BLAH cho một biến. Giả sử BLAH là định nghĩa tiền xử lý phổ biến trong nhiều tệp tiêu đề chuẩn (được định nghĩa là 10), vì vậy nếu tệp của tôi được bao gồm sau bất kỳ tệp nào, mã sẽ bị ngắt vì BLAH được chuyển thành 10; do đó, tôi phải #undef BLAH. Nhưng các tiêu đề khác có thể phụ thuộc vào BLAH, vì vậy tôi phải khôi phục BLAH thành giá trị ban đầu sau khi tiêu đề của tôi hoàn tất. Có thể thực hiện một việc như sau:

#ifdef BLAH 
#define BLAH_OLD BLAH 
#undef BLAH 
#endif 

... code ... 

// restore BLAH to 10 
#ifdef BLAH_OLD 
#define BLAH BLAH_OLD 
#end 

? Điều này không hiệu quả, bởi vì BLAH không được mở rộng đến 10. Tôi đã thử làm một cái gì đó như

#define EXPAND_AGAIN(x) x 
#define EXPAND(x) EXPAND_AGAIN(x) 
#define BLAH_OLD EXPAND(BLAH) 

nhưng điều đó không có tác dụng, vì EXPAND được thực hiện theo nghĩa đen và không được mở rộng. Tôi đang sử dụng MSVC 2008/2010, nhưng nó sẽ là đáng yêu nếu giải pháp sẽ làm việc trên hầu hết các trình biên dịch khác quá.

+3

Bạn đã cân nhắc việc thay đổi tên biến của mình chưa? –

+0

Thay đổi tên biến của bạn; quy ước khủng khiếp mà bạn đã đi đến đó nếu đây là vấn đề. Và làm thế nào về thay vì "chúng ta hãy nói" bạn nói "đây là vấn đề thực tế tôi đang cố gắng giải quyết." – GManNickG

+1

Bạn nhận ra rằng nó đã là một quy ước từ gần đầu thời gian mà các số nhận dạng được tất cả các mũ được dành riêng để sử dụng bởi các bộ xử lý trước (để tránh những thứ như thế này). –

Trả lời

-3

Một mẹo phù hợp với tôi là sử dụng enum trong lớp học.

class foo 
{ 
public: 
    enum { blah = 10 } myenum; 
} 

Sau đó, bạn chỉ có thể sử dụng

foo:blah 

khi bạn cần '10'.

Vì đó là một phần của lớp nên các ứng dụng khác của 'blah' sẽ không xung đột và bạn tiết kiệm tất cả những điều đó làm mất tinh thần và không hoàn thiện.

+1

Cái gì? '#define blah 0', ngắt mã của bạn. – GManNickG

+0

-1 để được tư vấn thường không hoạt động. Nếu "blah" đã được định nghĩa là macro tiền xử lý, thì định nghĩa enum có thể hầu như không được định dạng cú pháp. Khả năng vượt qua duy nhất là khi "blah" được định nghĩa là một số nhận dạng hợp lệ. Chúc mừng, –

+0

thay thế macro bằng enum và tất cả các vấn đề về xử lý các xung đột macro biến mất. Nó sẽ không sửa chữa 'đẩy' một giá trị. – Jay

0

Tôi đã từng tin rằng mẹo mà bạn đã thử rất giống nhau, vì tôi đã từng sử dụng nó. Nhưng cuối cùng tôi đã học được rằng nó thực sự không hoạt động chút nào. Câu trả lời đơn giản là KHÔNG, bạn không thể lưu giá trị hiện tại của một xác định, thay đổi nó, và sau đó khôi phục lại giá trị cũ. Bộ tiền xử lý đơn giản không hoạt động theo cách đó. Khi bạn xác định một giá trị mới, giá trị cũ sẽ biến mất.

19

Vâng, cho rằng trình biên dịch của bạn hỗ trợ các chỉ thị vĩ mô push/pop (visual C++, gcc, llvm bài làm):

#define BLAH 10 

#pragma push_macro("BLAH") 
#undef BLAH 

#define BLAH 5 

... 

#pragma pop_macro("BLAH") 
+0

Điều này có vẻ là trình biên dịch của Microsoft cụ thể. –

+0

Xin lỗi, tiêu chuẩn C++ không xác định 'push_macro' (Visual C++ có #pragma này, nhưng nó không phải là tiêu chuẩn C++). Chúc mừng, –

+0

Ít nhất một số phiên bản của GCC cũng hỗ trợ nó. –

4

Thật không may là tiền xử lý không hỗ trợ một chồng các định nghĩa.

Thư viện tiền xử lý tăng cường làm cho những điều bạn không bao giờ tưởng tượng nó có thể làm (như macro hiệu quả Vd trong C++ 98), nhưng bị ràng buộc bởi các giới hạn vốn có của bộ tiền xử lý - vì vậy, không thể thực hiện , lấy làm tiếc.

Cách khắc phục nửa chừng chỉ được biết là đặt trước ALL_UPPERCASE_IDENTIFIERS cho macro và luôn sử dụng chúng cho macro. Nó làm giảm vấn đề va chạm tên phần nào. Rất tiếc, thư viện chuẩn C xác định một số macro chữ thường hoặc cho phép sự tồn tại của chúng, ví dụ: ví dụ: assert, nhưng chúng chỉ là một vài.

Từ quan điểm thực tế, vấn đề chính là trong lập trình Windows, nơi các cửa sổ của Microsoft.h] tiêu đề xác định zillions của các macro không phải chữ hoa, bao gồm, theo mặc định, minmax xung đột với thư viện chuẩn C++.

Vì vậy, đối với lập trình Windows C++, hãy luôn xác định NOMINMAX trước khi bao gồm [windows.h].

Chúc mừng & hth.,

+0

cảm ơn 'NOMINMAX', nhưng có' #pragma push_macro' ít nhất – Sergei

+0

@Sergei: Có, '#pragma push_macro' là [giải pháp được chấp nhận trong câu hỏi trùng lặp] (http://stackoverflow.com/a/1794089/464581). Nhưng như tôi đã lưu ý trong một bình luận về một câu trả lời cho câu hỏi này, nó không chuẩn trong năm 2010. Tôi tin rằng nó vẫn không chuẩn, mặc dù nó được hỗ trợ bởi, ít nhất, Visual C++, g ++ và clang. –

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