Bộ tiền xử lý trong C




Bộ tiền xử lý trong C ở đây không phải là một phần của bộ biên dịch, nhưng có những bước riêng rẽ trong quá trình biên dịch. Theo cách hiểu cơ bản nhất, bộ tiền xử lý trong ngôn ngữ C là các công cụ thay thế văn bản và hướng dẫn trình biên dịch không yêu cầu tiền xử lý trước khi được biên dịch. Chúng tôi hướng đến bộ tiền xử lý C như CPP.

Tất cả các lệnh tiền xử lý bắt đầu với ký thự #. Nó ít nhất không phải là ký tự trắng, để dễ dàng đọc. Dưới đây là danh sách các thẻ tiền xử lý quan trọng.

Directive Miêu tả
#define Thay thể cho bộ tiền xử lý macro
#include Chèn một header đặc biệt từ file khác
#undef Không định nghĩa một macro tiền xử lý
#ifdef Trả về giá trị true nếu macro này được định nghĩa
#ifndef Trả về giá trị true nếu macro này không được định nghĩa
#if Kiểm tra nếu điều kiện biên dịch là đúng
#else Phần thay thế cho #if
#elif #else một #if trong một lệnh
#endif Kết thúc điều kiện tiền xử lý
#error In thông báo lỗi trên stderr
#pragma Thông báo các lệnh đặc biệt đến bộ biên dịch, sử dụng một phương thức được tiêu chuẩn hóa

Ví dụ bộ tiền xử lý trong C

Phân tích các ví dụ sau để hiểu các directive đa dạng.

#define DO_DAI_MANG_TOI_DA 20

Tiền xử lý này thông báo cho trình biên dịch C thay thế DO_DAI_MANG_TOI_DA với 20. Sử dụng #define cho các hằng số làm tăng khả năng đọc của chương trình.

#include <stdio.h>
#include "headercuatoi.h"

Tiền xử lý này thông báo cho trình biên dịch lấy thư viện stdio.h từ Thư viện hệ thống và thêm vào mã nguồn hiện tại. Dòng kế tiếp thông báo cho trình biên dịch lấy tệp headercuatoi.h từ thư mục máy tính và thêm nội dung và mã nguồn hiện tại.

#undef  KICH_CO_FILE
#define KICH_CO_FILE 42

Tiền xử lý này thông báo cho trình biên dịch vộ hiệu hóa biến KICH_CO_FILE và định nghĩa mới có giá trị 42.

#ifndef THONGDIEP
   #define THONGDIEP "Chao mung chang dep trai nhat nha!"
#endif

Điều này thông báo cho trình biên dịch ngôn ngữ C định nghĩa THONGDIEP nếu THONGDIEP không được định nghĩa.

#ifdef DEBUG
   /* tai day la phan lenh de debug cua ban */
#endif

Điều này thông báo cho tiền xử lý thao tác đoạn lệnh nếu DEBUG được định nghĩa.

Các Macro được định nghĩa trước trong C

ANSI C định nghĩa một số các macro. Mặc dù mỗi macro này có sẵn cho bạn sử dụng trong chương trình, bạn không nên chỉnh sửa một cách trực tiếp các macro được định nghĩa trước này.

Macro Miêu tả
__DATE__ Ngày hiện tại, như là một hằng số ký tự, trong định dạng "MMM DD YYYY"
__TIME__ Thời gian hiện tại, như là một hằng số ký tự, trong định dạng "HH:MM:SS"
__FILE__ Nó chứa tên file hiện tại như là một hằng số chuỗi
__LINE__ Nó chứa số dòng hiện tại như là một hằng số thập phân
__STDC__ Được định nghĩa là 1 khi bộ biên dịch biên dịch với chuẩn ANSI

Bạn thử ví dụ sau:

#include <stdio.h>

main()
{
   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );
   
   printf("\n===========================\n");
   printf("VietJack chuc cac ban hoc tot! \n");

}

Khi chương trình C trên trong file Untitled4.cpp được biên dịch và thực hiện. Nó sẽ in ra kết quả sau đây:

Bộ tiền xử lý trong C

Toán tử tiền xử lý trong C

Ngôn ngữ C cung cấp các toán tử sau giúp bạn tạo các macro:

Toán tử tiếp tục (\) của macro trong C

Một macro thường được bao gồm trong 1 dòng đơn. Toán tử tiếp tục của macro thường được sử dụng để tiếp tục một macro nếu có nhiều hơn một dòng. Ví dụ:

#define  thong_diep(a, b)  \
    printf(#a " va " #b ": nghia la Forever Alone!\n")

Dấu thăng (#) trong C

Toán tử stringize - dấu thăng ('#'), khi được sử dụng trong một định nghĩa macro, chuyển đổi một tham số macro thành một hằng số chuỗi. Toán tử này có thể sử dụng với macro để xác định một tham số cụ thể trong danh sách tham số. Ví dụ:

#include <stdio.h>

#define  thong_diep(a, b)  \
    printf(#a " va " #b ": nghia la Forever Alone!\n")

int main(void)
{
   thong_diep(F, A);
   
   printf("\n===========================\n");
   printf("VietJack chuc cac ban hoc tot! \n");
   return 0;
}

Biên dịch và thực thi chương trình C trên sẽ cho kết quả sau:

Bộ tiền xử lý trong C

Toán tử Token Pasting (##) trong C

Toán tử token pasting (##) sử dụng trong một định nghĩa macro kết nối 2 tham số. Nó cho phép 2 token riêng biệt trong định nghĩa marco có thể kết hợp thành 1 token. Do đó nó còn được gọi là toán tử ghép. Ví dụ:

#include <stdio.h>

#define vidutoken(n) printf ("token" #n " = %d", token##n)

int main(void)
{
   int token1 = 123;
   
   vidutoken(1);
   
   printf("\n===========================\n");
   printf("VietJack chuc cac ban hoc tot! \n");
   return 0;
}

Biên dịch và thực thi chương trình C trên sẽ cho kết quả sau:

Bộ tiền xử lý trong C

Nó xảy ra thế nào, bởi vì ví dụ này có kết quả là đầu ra thực sự từ bộ tiền xử lý:

printf ("token1 = %d", token1);

Ví dụ này chỉ ra sự móc nối của token##n trong token34 và ở đây chúng tôi đã sử dụng cả stringizetoken-pasting.

Toán tử defined() trong C

Toán tử tiền xử lý defined được sử dụng với biểu thức hằng để xác định nếu một định danh được định nghĩa bởi #define. Nếu định danh đã xác định được định nghĩa, thì giá trị là true (khác 0). Nếu chưa được định nghĩa thì giá trị là false (zero). Toán tử được định nghĩa được xác định như sau:

#include <stdio.h>

#if !defined (THONGDIEP)
   #define THONGDIEP "Chao mung chang dep trai nhat nha!"
#endif

int main(void)
{
   printf("Dev-C++: %s\n", THONGDIEP); 
   
   printf("\n===========================\n");
   printf("VietJack chuc cac ban hoc tot! \n"); 
   return 0;
}

Biên dịch và thực thi chương trình C trên sẽ cho kết quả sau:

Bộ tiền xử lý trong C

Macro tham số trong C

Một trong những tính năng mạnh mẽ của CPP là khả năng bắt chước các hàm bởi sử dụng các macro tham số. Ví dụ, chúng ta có thể có một đoạn code để bình phương một số như sau:

int binhphuong(int x) {
   return x * x;
}

Chúng ta có thể viết lại code trên bởi sử dụng một macro như sau:

#define binhphuong(x) ((x) * (x))

Các macro với các tham số phải được định nghĩa bởi sử dụng #define trước khi chúng có thể được sử dụng. Danh sách tham số được bao quanh trong dấu ngoặc đơn và phải ngay lập tức theo tên macro. Các khoảng trống là không được phép ở giữa tên macro và các dấu ngoặc đơn mở. Ví dụ:

#include <stdio.h>

#define LONNHAT(x,y) ((x) > (y) ? (x) : (y))

int main(void)
{
   printf("Gia tri lon nhat giua 123 va 321 la %d\n", LONNHAT(123, 321)); 
   
   printf("\n===========================\n");
   printf("VietJack chuc cac ban hoc tot! \n");  
   return 0;
}

Biên dịch và thực thi chương trình C trên sẽ cho kết quả sau:

Bộ tiền xử lý trong C

Loạt bài hướng dẫn học lập trình C cơ bản và nâng cao của chúng tôi dựa trên nguồn tài liệu của: Tutorialspoint.com

Follow fanpage của team https://www.facebook.com/vietjackteam/ hoặc facebook cá nhân Nguyễn Thanh Tuyền https://www.facebook.com/tuyen.vietjack để tiếp tục theo dõi các loạt bài mới nhất về Java,C,C++,Javascript,HTML,Python,Database,Mobile.... mới nhất của chúng tôi.

Các bài học lập trình C phổ biến khác tại VietJack: