2012-09-28 40 views
29

Tôi muốn in giá trị macro (mở rộng macro) trong chỉ thị #warning.Trình tiền xử lý C: mở rộng macro trong #warning

Ví dụ, đối với các mã:

#define AAA 17 
#warning AAA = ??? 

Các mong muốn sản lượng thời gian biên dịch sẽ

warning: AAA = 17 

để tôi sử dụng gì ???, hoặc, làm thế nào để tăng thêm mã ?

+1

Theo tiêu chuẩn C từ năm 1999, bạn chỉ có '# error' cho một cái gì đó như thế và nó không mở rộng bất kỳ macro nào, nó chỉ in văn bản theo nghĩa đen và làm cho trình biên dịch dừng lại. Những gì bạn đang cố gắng để đạt được với điều này anyway? –

+0

Tôi có một hệ thống phân cấp của nhiều makefiles xác định AAA theo nhiều cách khác nhau, tùy thuộc vào các tham số đích. Tôi muốn xác minh rằng định nghĩa là đúng cho mục tiêu. Và tôi không muốn tạo danh sách #if AAA = 1 ... #warning "là 1" ... – elomage

+0

Ngoài ra, điều này là dành cho thế giới được nhúng không có màn hình, vì vậy tôi không thể dễ dàng kiểm tra giá trị macro bằng thêm một cái gì đó như printf (#AAA); và kiểm tra nó trong thời gian chạy. – elomage

Trả lời

37

Bạn có thể sử dụng chỉ thị tiền xử lý #pragma message.

Ví dụ:

#define STR_HELPER(x) #x 
#define STR(x) STR_HELPER(x) 

#define AAA 123 
#pragma message "content of AAA: " STR(AAA) 

int main() { return 0; } 

Sản lượng có thể trông như thế này:

$ gcc test.c 
test.c:5:9: note: #pragma message: content of AAA: 123 
#pragma message("content of AAA: " STR(AAA)) 
     ^

Để tham khảo:

+0

Bạn nên đề cập đến trình biên dịch (s) mà tác phẩm này. '# pragma's' thực hiện cụ thể. –

+0

Làm việc với phiên bản gcc 4.5.3 (GNU GCC vá mspgcc-20110716), cảm ơn. – elomage

+2

hãy chắc chắn sử dụng '#pragma message' thay vì' # message' hoặc '# warning' – fantastory

2

Nhiều lần tôi có Makefile tạo tệp được tạo cục bộ.h chứa các định nghĩa mong muốn.

 
generated.h: Makefile 
     echo >generated.h "// WARNING: generated file. Change Makefile instead" 
     date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S' 
     echo >>generated.h "#if AAA == AAA_bad" 
     echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" 
     echo >>generated.h "#endif"

Sự cần thiết cho #include "generated.h" là hiển nhiên.

Tự nhiên bạn có thể xoay bất kỳ sự phức tạp nào ở đây, nhưng nếu nó có nhiều thì một vài dòng bạn có thể muốn đặt sự phức tạp vào một tập lệnh riêng biệt. Với một chút Imagination bạn có thể có các vòng lặp tạo ra một số lượng lớn các bài kiểm tra từ một đầu vào nhỏ.

Có mục tiêu được tạo.h phụ thuộc vào Makefile là rất quan trọng để đảm bảo được tạo.h được làm lại nếu các chỉ lệnh trong mục tiêu thay đổi. Nếu bạn có một tập lệnh generate.sh riêng biệt cũng sẽ nằm trong danh sách phụ thuộc.

Tuyên bố từ chối trách nhiệm: chưa được kiểm tra thực.

7

Tôi không khuyên bạn sử dụng #warning, vì nó không phải là tiêu chuẩn C. Bên cạnh đó, bạn muốn cảnh báo điều gì chứ không phải là lỗi? Cảnh báo thường là một cái gì đó trình biên dịch sử dụng khi bạn đang làm một cái gì đó là đáng ngờ của chúng tôi hoàn toàn nguy hiểm, nhưng được cho phép theo tiêu chuẩn C. Bạn không có trường hợp như vậy trong ứng dụng bình thường, bạn sẽ muốn nó hoặc là biên dịch hoàn hảo hay không. Do đó, tôi sẽ sử dụng #error tiêu chuẩn chứ không phải #warning không chuẩn.

Bạn không thể nhập nội dung thực tế của định nghĩa tiền xử lý. Một cái gì đó như thế này có thể đủ:

#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE) 
    #error AAA is bad. 
#endif 

Tôi nghĩ điều này đủ chi tiết cho người lập trình. Tuy nhiên, nếu bạn thực sự muốn biết thêm chi tiết và bạn có trình biên dịch C hiện đại, bạn có thể sử dụng static_assert.Sau đó, bạn có thể đạt được một cái gì đó gần với những gì bạn muốn:

#include <assert.h> 

#define xstr(s) str(s) 
#define str(s) #s 
#define err_msg(x) #x " is " xstr(x) 

#define AAA 17 

static_assert(AAA != 17, err_msg(AAA)); 

mớ hỗn độn macro này nên in AAA là 17. Giải thích về cách các macro làm việc có thể được tìm thấy here.

Tôi không chắc liệu static_assert có được bao gồm trong C99 hoặc C11 hay không, chắc chắn là trong C11. Bạn có thể phải sử dụng một số phần mở rộng GCC để kích hoạt nó.

+0

xem thêm [câu hỏi này] (http://stackoverflow.com/q/3385515/1025391) cho các xác nhận tĩnh trong C – moooeeeep

+0

Tôi chỉ cần một thông báo mang tính thông tin với giá trị để xác nhận sự nghi ngờ của tôi rằng một tham số nội bộ toàn cục không chính xác cho một trương hợp đ̣ăc biệt. Không có giá trị "xấu" ở đây. Hóa ra là nó không chính xác. Nhưng cảm ơn cho static_assert, nó hoạt động kể từ phiên bản g ++ 4.3 với tùy chọn -std = C++ 0x và phiên bản gcc 4.6 có static_assert được đặt bí danh thành _Static_assert mà không có tùy chọn. – elomage

+0

@elomage _Static_assert thực sự là một từ khóa trong C bây giờ, kể từ C11. chứa macro_assert vĩ mô, mở rộng thành _Static_assert. Một trong hai hình thức sẽ được sử dụng tốt vì chúng đều là tiêu chuẩn. – Lundin

7

Nếu bạn thực sự muốn phát ra cảnh báo, những điều sau cũng sẽ hoạt động. Tuy nhiên, nó phụ thuộc vào C99 được kích hoạt (chỉ hoạt động với gcc 4.8.2 hoặc mới hơn, chưa được thử nghiệm trên các phiên bản trước đó):

#define N 77 

#define __STRINGIFY(TEXT) #TEXT 
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT) 
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE)) 

#if N == 77 
_Pragma (WARNING(N)) 
#endif 
Các vấn đề liên quan