Lập Trình C++ B10: Chỉ Thị Tiền Xử Lý
Chỉ thị tiền xử lý trong lập trình c++
Chỉ thị tiền xử lý trong c++ là một kỹ thuật tạo ra những điều kiện xử lý mã code đối với trình biên dịch.
Ví dụ như thế này:
Bạn muốn một đoạn code A chỉ build trong môi trường win 64, còn trong môi trường win32 thì không được build.
Như vậy bạn không thể dùng cách thủ công đó là.
Cứ build ở mode 32 thì bạn comment đoạn code đó lại, và khi build ở win64 thì lại bỏ comment đoạn code đó.
Chúng ta cần nó auto, cần một cách thông minh hơn thế.
=> Và chỉ thị tiền xử lý được sử dụng trong trường hợp này.
I. LÝ THUYẾT CƠ BẢN.
Sau đây là cơ bản về các loại chỉ thị tiền xử lý thường hay được sử dụng.
1. #if …..[code block]…. #endif
– Nếu điều kiện if là đúng, thì code block được enable và được thực thi
– Nếu điều kiện if là sai, thì code block được disable và không được biên dịch
int main() { int a = 5; int b = 6; int c = 0; #if 0 c = a + b; #endif return 0; }
2. #if …..[code block 1]…#else…..[code block 2]…. #endif
– Nếu điều kiện if = TRUE, code block 1 được enable và thực thi
– Ngược lại thì code block 2 được enable và thực thi.
Ví dụ:
int main() { int a = 5; int b = 6; int c = 0; #if 0 c = a + b; #else c = a- b; #endif return 0; }
3. #ifdef ABC …[Code Block]. #endif
– Nếu ABC được định nghĩa code block sẽ được enable và thực thi
– Ngược lại thì code block sẽ bị disable và ko được biên dịch
Ví dụ:
#define ABC int main() { int a = 5; int b = 6; int c = 0; #ifdef ABC c = a + b; #endif #ifdef DEF c = a - b; #endif return 0; }
4. #ifndef ABC …[Code Block]. #endif
– Ngược lại so với case 3, nếu ABC không được định nghĩa thì code block sẽ được enable và thực thi
– Nếu ABC được định nghĩa thì code block sẽ được disable và không được biên dịch
-> Tương tự như vậy chúng ta cũng sẽ có
#ifdef …[code block 1] #else …[code block 2].. #endif
#ifndef…[code block 1] #else …[code block 2]…#endif
II. Ứng Dụng Thực TếChỉ thị Tiền Xử Lý.
1. Ứng dụng case 4 vào header guard.
Khi bạn tạo một file header mới và bạn khai báo trong đó một loạt các câu lệnh, các định nghĩa, các khai báo,….
và file header đó được gọi nhiều lần ở các nơi khác nhau.
Một lần gọi, thì các thủ tục trong file header đó sẽ được khai khai báo, xây dựng trong bộ nhớ.
Do đó nếu nhiều lần gọi thì các thủ tục sẽ liên tục được gọi lại, xây dựng lại.
Điều đó chưa thực sự tối ưu, và gây ảnh hưởng xấu đến việc quản lý và xây dựng vùng nhớ trong bộ nhớ chương trình.
Do đó người ta sử dụng kỹ thuật header guard để các thủ tục chỉ cần được gọi 1 lần.
Ví dụ sau đây mình họa cho điều này
#ifndef BASIC_FUNCTION_H_ #define BASIC_FUNCTION_H_ void FunctionAdd(); void FunctionSub(); void FunctionMul(); class BasicFunction { public: BasicFunction(); private: int a_; int b_; int c_; }; #endif
– Lần chạy 1: BASIC_FUNCTION_H_ là một chỉ thị bất kỳ tôi viết ra.
Chỉ thị này tôi chưa hề định nghĩ ở đâu do đó khối code bên trong được enable và thực thi.
=> Khi thực thi : tôi bắt đầu định nghĩa : BASIC_FUNCTION_H_, sau đó là một loạt các code khác như khai báo hàm , class…
– Lần chạy 2 : BASIC_FUNCTION_H_ đã được nghĩa rồi trong lần gọi thứ nhất, do đó đoạn code trong đó sẽ không được chạy vào, và không phải xây dựng lại các thủ tục khai báo hàm và các function.
—> ĐÂY CHÍNH LÀ KỸ THUẬT HEADER GUARD thường được sử dụng khi tạo mới các file header.
2. Ứng dụng chỉ thị tiền xử lý cho DEBUG VÀ RELEASE, 32 VÀ 64.
Trong các dự án lập trình với công cụ visual studio, đôi khi người lập trình cần phân biệt cấu hình build của dự án,
xem dự án sẽ build ở debug hay release, ứng dụng hệ 32 hay 64 bit để họ xây dựng những đoạn mã khác nhau,
nhằm giúp đỡ cho việc bảo trì, phát hiện lỗi, hoặc tương thích giữa các bản 32 và 64 bit.
Do vậy người ta sẽ sử dụng chỉ thị tiền xử lý để phân biệt.
Hình vẽ dưới đây mô tả việc sử dụng chỉ thị tiền xử lý trong VISUAL STUDIO
– WIN32/WIN64 sẽ được sử dụng để phân biệt cho cấu hình 32 và 64.
– _DEBUG và _NDEBUG sẽ được sử dụng phân biệt cho DEBUG và RELEASE
– Ngoài ra còn có nhiều các message khác để phần biệt các thành phần khác trong một dự án phần mềm.
3. Macro tiền định nghĩa:
C++ cung cấp cho chung ta một số lượng các tiền macro co sẵn như sau
[table id=2 /]
Nhưng vậy dựa vào những macro này chúng ta có thể tạo ra file log
để biết được thời điểm các file đang được biên dịch cũng như thông tin biên dịch về ngày tháng, giờ, phút….
Pingback: Học Lập Trình C++ Nâng Cao. Sử dụng Enum, Const và #Define
B Element Is Stored
B Element. What does this mean ?
chào anh, nếu như sử dung #pragma once thì có tiện lợi hơn chỉ thị #ifndef ko ạ?
#pragma once là thuộc về trình biên dich, chứ ko phải thuộc về lý thuyết c++. Nghĩa là nếu em dùng #prag… thì trong visual là ok. nhưng nếu sang một trình biên dịch khác, môi trường khác, ko có hỗ #prag thì sẽ lỗi. Và nếu dùng nhiều file thì việc sửa nó mất thời gian.
Người ta khuyến cáo dùng chỉ thị tiền xử lý tốt hơn.