Lập trình C – C #define

Lập trình C

– C #define

Bài trước

Bài sau

Chỉ thị tiền xử lý 

#define

Lệnh #define này cho phép khai báo một hằng số (constant) của tiền xử lý (preprocessor). Nó cho phép đưa giá trị số vào một từ.  

Cú pháp:

#define TEN giá trị  

Cần chú ý một chút về cách viết: tên của constant này thường được viết hoa toàn bộ, chủ yếu là để phân biệt với những constant mà ta được học trước đó : 
Ví dụ: 

const long MANG_SONG_NHAN_VAT_BAN_DAU = 3;

Những constant sẽ chiếm lấy một chỗ trong bộ nhớ, ngay cả khi giá trị không đổi, số « 3 » sẽ được lưu trữ đâu đó trong bộ nhớ. Không giống như trường hợp của các constant của preprocessor  
Vậy nó hoạt động như thế nào ? Đó là, #define sẽ thay thế tất cả những từ trong mã nguồn bởi giá trị tương ứng. Tương tự như chức năng « find/replace » trong word bạn thường sử dụng. 
Ví dụ:

#define MANG_SONG_NHAN_VAT_BAN_DAU 3 

Sẽ thay thế tất cả từ MANG_SONG_NHAN_VAT_BAN_DAU có trong file bằng giá trị 3 Và đây là một ví dụ :  
Một file.c trước khi qua preprocessor : 

Code C:

#define MANG_SONG_NHAN_VAT_BAN_DAU 3 
int main(int argc, char *argv[]) { 
long mang_song = MANG_SONG_NHAN_VAT_BAN_DAU; /* Code ...*/ 
 

Sau khi qua preprocessor : 
Code C : 

int main(int argc, char *argv[]) { 
long mang_song = 3; /* Code ...*/ 
 

Trước khi biên dịch, tất cả những  #define sẽ được thay thế bằng các giá trị tương ứng. Compiler sẽ thấy trong file sau khi qua tiền xử lý, trong đó tất các những chỗ cần thay thế đều đã được thực hiện  
Vậy đến thời điểm này, đâu là lợi ích của việc sử dụng những constant ?  
Ok, như tôi đã giải thích với bạn là nó không chiếm thêm bộ nhớ máy tính. Điều này có nghĩa là, đến giai đoạn compilation thì trong đó chỉ còn những con số trong mã nguồn của bạn.  
Một lợi ích khác khi sử dụng #define là việc thay thế sẽ được thực hiện trong tất cả các file chứa dòng #define. Khác với khi bạn khai báo một constant trong một function, nó chỉ có hiệu lực trong function đó, sau đó nó sẽ bị xóa đi.  
Nhưng đối với #define, nó sẽ tác động lên tất cả các function có trong file đó, và điều này thật sự rất tiện lợi cho những người lập trình.  
Bạn muốn một ví dụ cụ thể về việc sử dụng #define ?  
Đây là một ví dụ mà bạn có thể ứng dụng ngay. Khi bạn mở một cửa sổ chương trình bằng C, hẳn là bạn muốn xác định những constant của tiền xử lý đề chỉ ra kích thước của cửa sổ : 
Code C:

#define CHIEUDAI_CUASO 800 
#define CHIEURONG_CUASO 600 

Ưu điểm của việc này là nếu về sau bạn có ý định thay đổi kích thước của các cửa sổ (chẳng hạn như vì lý do chúng quá nhỏ), bạn chỉ cần thay đổi lại những dòng #define và sau đó biên dịch lại.  
Viết thêm rằng: những dòng #define thường được đặt trong những file.h, bên cạnh các prototype (Bạn có thể xem những file.h của các thư viện như stdio.h, bạn sẽ thấy ở đó luôn có những dòng #define !).  
Những #define giống như « cách thức đơn giản », giúp bạn thay đổi kích thước cửa sổ bằng việc thay đổi những #define, thay vì phải rà soát lại toàn bộ nội dung file tìm nơi mà bạn mở cửa sổ để thay đổi lại kích thước. Việc này sẽ tiết kiệm rất nhiều thời gian cho bạn trong việc lập trình.  
Tóm tắt lại, những constants của preprocessor cho phép « chỉnh sửa » chương trình của bạn trước việc compilation. Giống như một dạng mini-configuration. 

Define cho kích thước mảng

Ta thường dùng các define để xác định kích thước các table. Đây là ví dụ :  
Code  C :  

#define KICH_THUOC_TOI_DA 1000 
int main(int argc, char *argv[]) { 
char line1[KICH_THUOC_TOI_DA], line2[KICH_THUOC_TOI_DA]; 

Nhưng… tôi nghĩ rằng chúng ta không thể đặt biến số (KICH_THUOC_TOI_DA) giữa những dấu ngoặc [ ] khi khởi tạo table (line1[], line2[]) ?  
Đúng vậy, nhưng < KICH_THUOC_TOI_DA > KHÔNG phải là một biến số. Giống như tôi đã nói, preprocessor sẽ thay đổi nội dung của file trước khi compilation, như sau : 

Code C:

int main(int argc, char *argv[]) {
 char line1[1000], line2[1000]; 

…và đoạn code này là chính xác. Bằng cách xác định giá trị của KICH_THUOC_TOI_DA, các bạn có thể sử dụng nó để tạo những table có kích thước khác nhau. Nếu trường hợp sau này table đang sử dụng không đủ lớn, bạn chỉ cần thay đổi giá trị ở dòng #define, sau đó compile lại, và table dạng char của bạn đã sẽ nhận kích thước mới mà bạn vừa thay đổi. 

Tính toán trong define 

Chúng ta có thể thực hiện một vài phép tính trong define.  
Ví dụ, đoạn code sau sẽ tạo constant CHIEUDAI_CUASO và CHIEURONG_CUASO, sau đó là SOLUONG_PIXELS chứa số lượng pixel hiển thị trong cửa sổ. (việc tính toán khá đơn giản: chiều rộng*chiều dài) : 
Code C:  

#define CHIEUDAI_CUASO 800 
#define CHIEUCAO_CUASO 600 
#define SOLUONG_PIXELS (CHIEUDAI_CUASO * CHIEUCAO_CUASO) 

 
Giá trị của SOLUONG_PIXELS được thay đổi trước khi compile bằng giá trị của (CHIEUDAI_CUASO * CHIEUCAO_CUASO), có nghĩa là (800*600), 480000.  
Hãy luôn đặt phép tính của bạn trong những dấu ngoặc đơn như cách tôi đã làm.  
Bạn có thể thực hiện tất cả các phép toán cơ bản mà bạn biết: phép cộng (+), phép trừ (-), phép nhân (*), phép chia (/) và modulo (%).  

 

Bài trước

Bài sau