Table of Contents
Các tác giả có thể xác định các hằng số, đoạn cắt thẳng và thực hiện tính toán. Khi sử dụng hiệu quả, họ tăng cường đáng kể khả năng phục hồi mã và duy trì, cho phép các nhà phát triển viết ra các chương trình làm sạch, linh hoạt hơn. Tuy nhiên, sức mạnh của các lập trình viên có rủi ro; cách sử dụng sai số có thể gây ra lỗi và làm cho mã hóa khó hơn để gỡ lỗi. Bài này khám phá cách khai thác các vĩ mô tối đa trong khi tránh hố sụp đổ thường, với các thực hành rút ra từ kinh nghiệm công nghiệp và tiêu chuẩn C.
Macros là gì?
Các vĩ lệnh được định nghĩa bằng chỉ thị và được xử lý bởi trình xử lý trước khi hợp nhất bắt đầu. Các vĩ lệnh trước khi tiến trình này được xác định bằng chỉ thị [FLT: 0]. Các vĩ lệnh trước khi tiến hành thay thế văn bản đơn giản: mỗi lần trong mã nguồn được thay thế bằng định nghĩa vĩ mô. Việc thay thế này hoàn toàn theo định nghĩa chữ và không tôn trọng phạm vi hay kiểu kiểm tra. Các vĩ mô có thể [FL: 0] giống như[FL: 1) [FL: 1] [FT: 1] (không thay thế hằng số) hoặc [FL] như [FL].
#define PI 3.14159 // object-like macro
#define SQUARE(x) ((x)*(x)) // function-like macro
Hiểu được bước xử lý này là rất quan trọng vì vĩ mô không tuân theo cùng các quy tắc như hàm số hoặc biến số. chúng được mở rộng trực tiếp, giúp chúng có lợi thế hiệu quả nhưng cũng đưa ra những thách thức độc đáo.
Lợi ích của các vĩ lệnh để chứng minh tính bền vững và bảo trì
Khi áp dụng một cách chu đáo, vĩ mô cung cấp một số lợi thế cụ thể trong mã lớn hoặc hiệu suất nhạy cảm:
- Tính năng Reution ): xác định một phép tính hoặc trích một lần và dùng nó trong suốt chương trình. Thay đổi bản cập nhật vĩ mô mỗi lần tự động.
- Thay vì phân tán các nghĩa đen như ) hoặc , cho chúng những tên đầy ý nghĩa. Điều này cải thiện khả năng đọc và làm cho tham số dễ thay đổi.
- Thành tựu sinh ): hàm số tránh chi phí của một cuộc gọi chức năng. Đối với hoạt động nhỏ thường xuyên (v. d., min/max, square), vĩ mô có thể nhanh hơn cả chức năng inlines trong một số bộ biên dịch không được bảo đảm.
- , và để bao gồm hoặc loại bỏ các mã dựa trên điều kiện biên dịch thời gian. Điều này cần thiết cho các mã đặc trưng, gỡ lỗi xây dựng, hoặc bật/tắt.
- Cấu hình kiểu sao ). [FLT: 0] [FLT:] [FLT: 1]]: bằng cách xác định vĩ mô với giá trị khác nhau trong đầu trang riêng, bạn có thể điều chỉnh ứng xử của toàn bộ mã cơ sở [FLT: 1] bằng cách không cần tiếp xúc tập tin.
Viết các vĩ châm trắng: Cách thực hành tốt nhất
Sự linh hoạt của vĩ mô cũng là mối nguy hiểm của chúng. một vĩ mô không được viết dở có thể gây ra những hành vi bất ngờ khó để theo dõi. theo những cách tốt nhất để giữ cho vĩ mô của bạn an toàn và có thể bảo tồn.
Luôn luôn phân tích tham số và biểu thức toàn bộ
Vì vĩ mô là văn bản thay thế, người điều hành có thể phá vỡ chúng. Một vĩ mô như sẽ mở rộng [FLT: 9) (có nghĩa là 11 không phải 25). Việc sửa đổi là gửi kèm mỗi tham số trong ngoặc và gói toàn bộ biểu thức:
#define SQUARE(x) ((x) * (x)) // now SQUARE(3+2) works correctly
Tránh nhiều đánh giá những cuộc tranh cãi
Đối số Macro được thay thế như-is. Nếu một đối số có tác dụng phụ (v., , nó có thể được đánh giá nhiều hơn một lần. Ví dụ:
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int x = 5;
int max = MAX(x++, 10); // expands to ((x++) > (10) ? (x++) : (10)) // x incremented twice!
Để tránh điều này, hãy chọn chức năng trực tiếp hoặc dùng các đại hội tên một cách cẩn thận để cảnh báo người dùng. Nếu bạn cần phải dùng vĩ mô, tài liệu không nên chứa tác dụng phụ.
Dùng chữ trên cho các tên vĩ lệnh
Theo hội nghị, vĩ mô được viết bằng chữ hoa (v. d., , .
Kết thúc Macro với « Do- in » cho khối đa phân
Khi xác định một vĩ mô chứa nhiều lời tuyên bố, hãy quấn chúng trong vòng . Điều này đảm bảo vĩ mô ứng xử đúng trong mọi ngữ cảnh (v. d., sau khi không có dây chằng):
#define LOG_ERROR(msg) do { \
fprintf(stderr, "Error: %s\n", msg); \
exit(1); \
} while (0)
Tài liệu vĩ lệnh một cách hoàn hảo
Các vĩ lệnh thiếu tự thống kê các chức năng. Luôn luôn thêm các bình luận mô tả các đối số, mong đợi hành vi và bất kỳ giới hạn nào. Dùng bình luận kiểu Doxygen khi thích hợp.
Công nghệ vĩ mô vĩ mô cao cấp
Các bộ xử lý C cung cấp các nhà điều hành mạnh mẽ mà đi xa hơn so với thay thế đơn giản. làm chủ những thứ này có thể làm cho vĩ mô của bạn còn linh hoạt hơn.
Chuỗi hoá
Người điều khiển biến một đối số vĩ mô thành một chuỗi theo nghĩa đen. Điều này có ích cho việc gỡ lỗi hoặc ghi nhật ký:
#define PRINT_VAR(x) printf(#x " = %d\n", x)
int value = 42;
PRINT_VAR(value); // prints: value = 42
Token Pasting với
Người điều khiển phân loại hai vật thể thành một vật thể riêng lẻ. Tính năng này cho phép bạn tạo bộ nhận diện động theo thời gian biên dịch:
#define CREATE_VAR(prefix, index) prefix ## index
int CREATE_VAR(arr, 0) = 10; // becomes int arr0 = 10;
Việc dán ảnh được sử dụng rộng rãi trong X vĩ mô và để tạo ra các mẫu mã lặp lại.
Đa thức vĩ lệnh (C99)
Giới thiệu trong C99, vĩ mô biến số chấp nhận một số biến số dùng . Điều này cho phép ghi nhật ký linh hoạt và gỡ lỗi vĩ mô:
#define DEBUG_PRINT(fmt, ...) \
fprintf(stderr, "DEBUG: " fmt, __VA_ARGS__)
DEBUG_PRINT("x = %d, y = %d", x, y);
Trong C11 và sau đó, bạn có thể dùng để xử lý dấu phẩy trong các lý luận rỗng, cải thiện khả năng chuyển tiếp.
Những cạm bẫy thông thường và cách tránh chúng
Thậm chí những nhà phát triển có kinh nghiệm C cũng gặp những con bọ có liên quan đến vĩ mô.
- Một vĩ mô mở rộng đến một khối mà không có dấu chấm phẩy có thể gây ra lỗi cú pháp.
- Người giải thích bất ngờ [FLT: 1]: luôn luôn chấp nhận [như đã ghi trên.
- Nếu bạn định nghĩa vĩ mô với cùng tên với một chức năng thư viện chuẩn, nó có thể âm thầm ghi đè lên nó. Dùng tên độc nhất hoặc #undef.
- Không-constant fFLT bản [FLT: 1]]: các vĩ mô vật thể được sử dụng như hằng số, nhưng không được gõ. Chúng có thể được sử dụng trong các biểu thức liên tục chỉ nếu chính sự mở rộng là một biểu thức thường xuyên.
- Khó khăn giảm dần ): Macros được mở rộng trước khi biên dịch thấy chúng, nên thông điệp lỗi chỉ đến mã mở rộng, chứ không phải tên vĩ mô. Việc dùng cờ với GCC hoặc Clang (v. g., cho thấy kết quả trước khi có dấu vết.
Các lựa chọn khác cho Macros: const, enum, và Iline jaws
C hiện đại cung cấp những phương án an toàn hơn mà thường loại bỏ nhu cầu về vĩ mô:
- biến [FLT:]] [FLT: 1]]: Đối với hằng số, hãy . Họ có thể được dùng cho kích cỡ dãy nếu biến số là hằng số (v. [FL:33].
- ) ) Đối với một tập hợp các số nguyên liên quan, ennums là an toàn kiểu và tự động định nghĩa các giá trị. Chúng được sử dụng rộng rãi cho các mã lỗi và cờ.
- Chức năng ): Giới thiệu trong C99, cung cấp hiệu suất của vĩ mô với mức độ an toàn loại đầy đủ, hỗ trợ gỡ lỗi, và tránh các vấn đề tác động phụ. Ví dụ:
static inline int square(int x) {
return x * x;
}
Dùng chức năng trực tiếp khi nào cần một vĩ mô chức năng để đánh giá các đối số chính xác một lần. Trường hợp duy nhất còn lại cho vĩ mô giống chức năng là khi bạn cần phải hoạt động trên kiểu (v. d., kiểu của GNU C) hoặc cần khả năng mở một phạm vi mới (như dạng ngôn ngữ làm việc thời).
Ví dụ thực tế: gỡ lỗi và cấu hình
Các vĩ mô xuất sắc trong trường hợp có điều kiện.
Name
#ifdef DEBUG
#define LOG(fmt, ...) fprintf(stderr, "[DEBUG] " fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...) /* no-op */
#endif
Bản ghi vĩ mô này chỉ được biên dịch với , và vĩ mô rỗng gây ra 0 trên đầu trong việc phát hành. Bản trước là phần mở rộng GNU loại bỏ dấu phẩy theo sau khi không có đối số nào được cung cấp (cũng được hỗ trợ vào năm 20 với .
Comment
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM "Windows"
#elif defined(__linux__)
#define PLATFORM "Linux"
#else
#define PLATFORM "Unknown"
#endif
Cấu hình này tách các quan hệ phụ thuộc ra mà không cần phức tạp toàn bộ chức năng. Kết hợp với lính canh, nó giữ cho người dẫn đầu được sạch sẽ và bảo trì.
Kết luận
Các vĩ lệnh vẫn còn là một công cụ không thể thiếu trong C để phục hồi mã và bảo trì. Đặc biệt trong bối cảnh hiện đại hoặc tích hợp, nơi mà mọi chức năng hay các chuỗi tính chung. Khi sử dụng đúng (với dấu ngoặc), hiệu phụ hạn chế, và tên thích hợp - họ giảm khả năng lặp và cấu hình tập trung. Tuy nhiên, xu hướng trong hiện đại C là thay thế hàm số giống như hàm số hay tổng hợp (dùng trong C11) để đạt được an toàn và khả năng gỡ lỗi loại. Để đạt được các vĩ mô như đối tượng, [FT:45] và [L: 46] thường xuyên cao hơn.
Bằng cách cân bằng quyền lực vĩ mô truyền thống ) và ) ) tham khảo thêm . Hiểu rõ các cạm bẫy lớn (FLT:1) cũng được bao gồm trong trang [FL:4] này [FLT: 1].com ).