Kinh Nghiệm về Bộ tiền xử lý c được chỉ định bằng ký hiệu: Chi Tiết

Bạn đang tìm kiếm từ khóa Bộ tiền xử lý c được chỉ định bằng ký hiệu: được Update vào lúc : 2022-08-08 02:30:20 . Với phương châm chia sẻ Bí kíp Hướng dẫn trong nội dung bài viết một cách Chi Tiết Mới Nhất. Nếu sau khi Read tài liệu vẫn ko hiểu thì hoàn toàn có thể lại Comments ở cuối bài để Ad lý giải và hướng dẫn lại nha.

Bộ tiền xử lý – Lập trình C : Bài 20

1. Giới thiệu

Trong những bài đã trình diễn ở những phần trước, toàn bộ chúng ta đã sử dụng những thông tư như #include, #define, và toàn bộ chúng ta cũng không cần quan tâm rõ ràng về những thông tư này hoạt động và sinh hoạt giải trí ra làm sao.

Thực chất những thông tư #include, define và một số trong những những thông tư khác được xử lý bởi bộ tiền xử lý (prepeocessor). Bộ tiền xử lý theo định nghĩa nó là một phần phần nhỏ và được biên soạn bởi chương trình C. Nó thực thi trước lúc thực thi biên dịch chương trình.

Bộ tiền xử lý là một công cụ mạnh mẽ và tự tin của lập trình C. Tuy nhiên với những lập trình viên khi xuất hiện lỗi với bộ tiền xử lý thì yếu tố tìm ra bugs là một thử thách. Ngoài ra bộ tiền xử lý rất dễ dàng gây ra ra việc sử dụng sai và nó cũng là nguyên nhân gây ra sự khó hiểu của chương trình. Tuy nhiên với sức mạnh và tính tiện lợi của cục tiền xử lý vẫn được sử dụng rộng dãi khi xây dựng những ứng dụng bằng việc sử dụng ngôn từ lập trình C.

1.1. Sử dụng bộ tiền xử lý:

Xét theo khía cạnh tổng quát trong tăng trưởng và xây dựng ứng dụng thì bộ tiền xử lý được sử dụng để xử lý và xử lý những trường hợp:

Tính khả chuyển – Portability: Xây dựng ứng dụng C cần tương hỗ chạy trên nhiều những nền tảng Hệ điều hành quản lý hoặc những môi trường tự nhiên vạn vật thiên nhiên rất khác nhau là một yêu cầu trên thực tiễn. Bộ tiền xử lý sẽ là một cách thuận tiện để đảm bảo tính khả chuyển của khối mạng lưới hệ thống khi khối mạng lưới hệ thống chạy trên nhiều hệ điều hành quản lý, môi trường tự nhiên vạn vật thiên nhiên rất khác nhau. Ví dụ : Lập trình viên sử dụng những thông tư Đk (#if, #else, # if defined …) để kiểm tra những thiết lập cho chương trình khi chạy trên những hệ điều hành quản lý, môi trường tự nhiên vạn vật thiên nhiên rất khác nhau. Dựa trên những thông tin đã được thiết lập này, lập trình viên sẽ sử dụng một số trong những những macro, những thư viện.. tương ứng với từng hệ điều hành quản lý, môi trường tự nhiên vạn vật thiên nhiên rõ ràng. Ví dụ sử dụng #include khi chương trình C chạy trên hệ điều hành quản lý Linux hoặc MacOS…

Tính biến hóa – Variability: Lập trình viên thường sủ dụng thông tư Đk (#if, #else, # if defined …) để phục vụ những đặc tính tùy chọn hoặc để lựa chọn một trong những giải pháp thực thi. Ví dụ : Sử dụng thông tư Đk để vô hiệu một phần thư viện không thiết yếu của ứng dụng nhằm mục đích tăng tính hiệu năng của khối mạng lưới hệ thống và giảm kích cỡ ứng dụng. Tính năng DEBUG là một ví dụ về vấn để này. Sử dụng DEBUG thường là để in ra dòng thông báo khi chương trình xẩy ra lỗi, với những người tiêu dùng cuối DEBUG không còn ý nghĩa tuy nhiên với lập trình viên, sử dụng DEBUG để ngăn ngừa những lỗi xẩy ra không đáng có và hoàn toàn có thể là nguyên nhân gây ra chương trình bị lỗi.

Tối ưu mà – Code Optimization: Một số nhà lập trình viên nhận định rằng, ngoài việc loại trừ một số trong những hiệu suất cao không thiết yếu, họ cũng sử dụng những thông tư Đk nhằm mục đích để tối ưu những đoạn mã và giảm kích cỡ chương trình.

Tiến hóa mã – Code Evolution: Một số lập trình viên thường sử dụng những thông tư Đk để khi tăng cấp hoặc tối ưu Code gắn với một hiệu suất cao nào đó. (Sử dụng thông tư có Đk hoàn toàn có thể thiết lập một hàm hay một nhóm hàm gắn với một hiệu suất cao rõ ràng hoàn toàn có thể chạy trên nhiều phiên bản rất khác nhau. Điều này được cho phép những lập trình viên hoàn toàn có thể kiểm định được những tính năng mới tăng trưởng của khối mạng lưới hệ thống.

Giới hạn ngôn từ – Language Limitations: Một số nhà tăng trưởng đề cập đến việc sử dụng những thông tư có Đk vì những hạn chế của ngôn từ C. Ví dụ : Họ sử dụng #ifdef để kiểm tra tránh việc sử dụng cùng lúc nhiều những tệp header.

1.2. Bộ tiền xử lý trong lập trình

Cụ thể trong lập trình bộ tiền xử lý được sử dụng để:

Bao hàm những tệp header : Khi xây dựng khối mạng lưới hệ thống những lập trình thông thường phải gọi đến những thư viện được phục vụ sẵn bởi ngôn từ lập trình C. Để thực thi điều này thì những lập trình viên thường sử dụng thông tư #include để thực thi.

Mở rộng và định nghĩa những macro: Các lập trình viên hoàn toàn có thể định nghĩa những macro, đó là những chữ viết tắt cho những đoạn mã C tùy ý. Bộ tiền xử lý sẽ thay thế những macro bằng định nghĩa của chúng trong suốt chương trình. Một số macro được C định nghĩa sẵn.

Chỉ thị có Đk: Trong một số trong những những trường hợp lập trình viên nên phải vô hiệu hoặc gồm có (chứa) những đoạn mã của chương trình.

Chẩn đoán: Trong quy trình chạy chương trình, chương trình hoàn toàn có thể bị lỗi, sử dụng bộ tiền xử lý để ngăn cản những lỗi phát sinh không đáng có và thông báo cho những nhà tăng trưởng và người tiêu dùng. Ví dụ như dùng DEBUG.

1.3 Bộ tiền xử lý thao tác ra làm sao

Các hành vi của cục tiền xử lý được điều khiển và tinh chỉnh bởi những thông tư của cục tiền xử lý: Các thông tư được ghi lại khởi đầu bằng kí tự #, toàn bộ chúng ta đã gặp 2 tiền xử lý #include và #define ở những phần mà tôi đã trình diễn.

Chỉ thị #define định nghĩa một macro gồm mang tên của macro và thực thể của nó (đôi lúc nó hoàn toàn có thể như một hằng hoặc là một biểu thức). Khi một tiền xử lý được sử dụng trong chương trình, chương trình gặp tên marcro thì nó sẽ thay thế tên macro đó bằng chính nội dung của macro.

Chỉ thị #include thông báo cho bộ tiền xử lý mở một file được xác lập thông qua tên file với nội dung gắn với file này và coi nội dung file như thể một phần đã được biên dịch bởi chương trình.

Ví dụ : #include

Chỉ thị cho bộ tiền xử lý mở file stdio.h và mang nội dung của file này vào trong chương trình. Stdio.h chứa những nguyên mẫu của những hàm vào/ra chuẩn của ngôn từ C.

Lược đồ mô tả thứ vai trò của cục tiền xử lý trong biên dịch chương trình.

Hình số 1 : Vai trò tiền xử lý trong xử lý chương trình C

Đầu vào của tiền xử lý là chương trình C. Trong chương trình C chứa những thông tư và bộ tiền xử lý sẽ thực thi những thông tư. Đầu ra của khi kết thúc quy trình tiền xử lý là một chương trình C khác, phiên bản mới sẽ tiến hành update và không hề chứa những thông tư của cục tiền xử lý nữa (Vì những thông tư của cục tiền xử lý đã được thay thế bằng nội dung của nó). Nội dung này sẽ làm nguồn vào trực tiếp cho trình biên dịch. Trình biên dịch sẽ thực thi kiểm tra cú pháp, ngữ nghĩa khi thực thi biên dịch chương trình.

2. Chỉ thị tiền xử lý Include

Chỉ thị Tiền xử lý #include được sử dụng để chèn tệp tiêu đề vào chương trình thông qua cú pháp :

#include

Hoặc

#include “filename”

Các file được thông tư tiền xử lý thông qua #include được gọi là những header file(file tiêu đề). File tiêu đề là file chứa những khai báo hoặc những định nghĩa macro và hoàn toàn có thể là cả tài liệu mang tính chất chất toàn cục. Các file tiêu đề này hoàn toàn có thể được chia sẻ ở nhiều những file chứa mã nguồn xử lý trách nhiệm của chương trình.

Lưu ý : filename hoàn toàn có thể là tên thường gọi file khá đầy đủ của file header hay nói cách khác là hoàn toàn có thể chứa cả đường dẫn tới file header.

Ví dụ :

#include

Trong hệ điều hành quản lý Unix, thì với trình biên dịch C thuần, những file header sẽ nằm ở vị trí thư mục /usr/include.

Khi thực thi thông tư #include thì chương trình sẽ thực thi tìm kiếm những file tiêu đề tại thự mục mặc định hoặc lại thư mục chứa những file .c (mã nguồn của chương trình).

2.1. Các file tiêu đề phục vụ 2 mục tiêu

+ File tiêu đề chứa những khai báo và những macro được tương hỗ sẵn bởi ngôn từ C. File tiêu đề có đuôi mở rộng là .h; Khi những lập trình viên cần sử dụng thì sẽ sử dụng #include để gọi đến thư viện chứa những file tiêu đề này.

+ Các file tiêu đề (header) do những lập trình viên tự định nghĩa. Khi đó nó sẽ đóng vai trò như thể những interface thực thi tiếp xúc Một trong những file nguồn trong chương trình. Khi xây dựng chương trình, bạn cần nhóm những yếu tố có liên quan với nhau và định nghĩa những marcro cho việc xử lý tập hợp yếu tố phát sinh thì bạn lên sử dụng file tiêu đề để chứa những thông tin này.

Thực chất quy trình sử dụng thông tư #include hoặc #include “filename” tại những file nguồn .c có kết quả in như thể thực thi copy nội dung của file header vào trong file nguồn .c của chương trình. Tuy nhiên nếu thực thi copy (Theo nghĩa thông thường) thì sẽ gây nên mất thời hạn và rất dễ dàng lỗi. Với file header, việc khai báo thông qua việc sử dụng #include chỉ xuất hiện ở một nơi trong file nguồn (file .c).

Nếu vì một nguyên do nào đó cần update những file header thì quy trình này sẽ tiến hành thực thi tại nơi chứa những file header, và tại file nguồn không cần sửa đổi gì cả và nội dung thực thi của chương trình sẽ tự động hóa update lại khi chương trình được biên dịch lại.

Ví dụ :

Khi toàn bộ chúng ta thao tác với tài liệu file, toàn bộ chúng ta phải sử dụng những hàm như fopen khi đó toàn bộ chúng ta nên phải tương hỗ update thông tư bộ tiền xử lý sau :

#include

Trong nội dung của file studio.h chứa nội dung là những nguyên mẫu những hàm như sau :

FILE *fopen( const char *, const char * );

size_t fread( void *, size_t, size_t, FILE * );

FILE *freopen( const char *, const char *, FILE * );

char *tempnam( char *, char * );

FILE *tmpfile( void );

char *tmpnam( char * );

extern long ftell( FILE * );

2.2. Sử dụng file tiêu đề để chứa tài liệu toàn cục

Khi lập trình, những lập trình viên hoàn toàn có thể khai báo biến

int global_counter;

char global_char;

main()

Khi đó những biến global_counter, global_char sẽ tiến hành sử dụng trên phạm vi toàn bộ chương trình. Ngoài cách này ra thì những lập trình viên hoàn toàn có thể định nghĩa những biến này trong file header như sau:

Tạo file “global_decs.h”, trong file global_decs.h chứa những khai báo

int global_counter;

char global_char;

Khi đó trong những đoạn mã muốn sử dụng 2 biến này toàn bộ chúng ta sẽ phải

#include “global_decs.h”

2.3. Khai báo biến toàn cục với từ khóa extern

Trong lập trình C, sử dụng từ khóa extern để khai báo một biến sử dụng chung mang tính chất chất toàn cục trong phạm vi của một module nào đó. Khi khai báo một biến có từ khóa extern thì biến này sẽ tránh việc phải lập giá trị ban đầu tại file header thay vào đó lập trình viên sẽ tạo giá trị của biến này tại những file nguồn .c; Lưu ý tại file header khi khai báo biến với từ khóa extern nên phải sử dụng comment để ghi chú thích riêng với từng biến.

Ví dụ

Định nghĩa file globalvar.h có nội dung

/* Initialized to 1 in start.c */

extern int page_num;

Khi đó tại file start.c lập trình viên sẽ sử dụng

int page_num = 1;

Khi gặp từ khóa extern trình biên dịch sẽ hiểu là biến này sẽ tiến hành khai báo ở phạm vi toàn cục, không thiết yếu lập giá trị trước (Có nghĩa là tránh việc phải để giành vùng bộ nhớ trống cho biến này) và biến này sẽ tiến hành thiết lập giá trị tại những file nguồn .c khi cần.

3. Macro

3.1 Định nghĩa Macro như một hằng

Cú pháp :

#define name_macro body_macro

Trong số đó :

name_macro : là tên thường gọi macro, body_macro: Nội dung macro hay thân macro.

Một macro là một tên có chứa chuỗi ký tự liên quan. Chuỗi ký tự này được gọi là nội dung hay thân của macro (macro body toàn thân).

Trong C, sử dụng những chữa cái Hoa để tại vị tên cho những macro, điều này được sử dụng để phân biệt giữa tên những macro với tên những biến (thông thường tên những biến sử dụng cả vần âm hoa và thường).

Ví dụ

#define PI 3.14159

#define BUFF_LEN 512

Tên macro : PI, BUFF_LEN

Nội dung macro tương ứng với PI là : 3.14159 và tương ứng với BUFF_LEN là 512

Khi lập trình thay vì phải khai báo : char buf [512] thì toàn bộ chúng ta sử dụng char buf [BUFF_LEN];

Với những lập trình viên còn ít kinh nghiệm tay nghề, khi lập trình toàn bộ chúng ta thường hay viết như sau :

static char in_buf[256];

main()

for (a = 0; a < 256 ; a++)

                    in_buf[al = getchar();

Khi chạy chương trình toàn bộ chúng ta thấy giá trị 256 không đủ để lưu thông tin, lập tức toàn bộ chúng ta phải sửa đổi giá trị 256 này. Lúc đó toàn bộ chúng ta phải sửa ở cả 2 vị trí chứa số 256. Nếu một chương trình có nhiều chỗ sử dụng giá trị 256 thì lập tức toàn bộ chúng ta gặp yếu tố. Như vậy thay vì sử dụng giá trị trực tiếp 256 toàn bộ chúng ta sẽ thay thế nó bằng :

#define MAX_INPUT_BUFFER_SIZE 256

static char in_buf[MAX_INPUT_BUFFER_SIZE];

main()

for (a = 0; a < MAX_INPUT_BUFFER_SIZE; a++)

                    in_buf[al = getchar();

3.2. Macro với tham số

Tương tự như hàm, macro hoàn toàn có thể có chứa một hoặc nhiều tham số nguồn vào, những tham số này sẽ tiến hành sử dụng tại nội dung (macro body toàn thân) hay tại thân của macro:

Hình sau mô tả định nghĩa macro với tham số:

Hình số 2 : Macro có tham số

Ví dụ : Macro có một tham số

#define CIRCLE_AREA(x) ((PI) * (x) * (x))

Thay vì viết hàm tính diện tích s quy hoạnh đường tròn với bán kính x; sử dụng macro để thực thi

Tên macro là : CIRCLE_AREA

Tham số truyền vào : x;

Nội dụng của macro: ((PI) * (x) * (x))

Khi lập trình sử dụng macro CIRCLE_AREA như sau:

float area = CIRCLE_AREA(4);

thì sẽ tiến hành dịch ra bởi bộ tiền xử lý là

float area =((PI)*(4)*(4));

Ví dụ : Với macro có 2 tham số

#define RECTANGLE_AREA(x, y) ((x) * (y))

Khi đó trong code

int rectArea = RECTANGLE_AREA(5, 6);

thì sẽ tiến hành dịch ra bởi bộ tiền xử lý là :

int rectArea = ((5) * (6));

3.3 Cảnh báo lỗi

3.3.1 Sử dụng dấu ;

Một trong những lỗi xẩy ra khi lập trình đó là sử dụng định nghĩa marcro có chứa dấu ; ở cuối dòng định nghĩa marco

Ví dụ

#define SIZE 10;

Khi sử dụng macro SIZE như sau

int i = SIZE;

Thì sẽ tiến hành dịch ra bởi bộ tiền xử lý như sau

int i = 10;;

và thời gian hiện nay sẽ xuất hiện lỗi, với những lập trình viên ít kinh nghiệm tay nghề thì sẽ rất khó tìm ra lỗi này.

Một ví dụ khác :

#define GOOD_CONDITION (var == 1);

Sau đó sử dụng macro GOOD_CONDITION vận dụng với while

while GOOD_CONDITION

          …

Bộ tiền xử lý sẽ xử lý như sau

while (var == 1);

          …

Và lúc này sẽ gây nên lỗi vì kết quả là nội dung thực thi trong while sẽ không còn hề là một nội dung của while nữa.

3.3.2. Thứ tự thực thi những phép toán
Do đặc trưng macro nên lúc sử dụng macro cần rất lưu ý về thứ tự ưu tiên ví dụ

#define RECTANGLE_AREA(x, y) (x * y)

Có nghĩa ở nội dung macro RECTANGLE_AREA ta thay thế ((x)*(y)) bằng (x * y) khi đó ta sử dụng:

int i = RECTANGLE_AREA(a+2,b); Lúc này bộ tiền xử lý sẽ thực thi

int i = a+2*b; và thời gian hiện nay kết quả sẽ khác (a+2) * (b);

3.3.3. Sử dụng dấu = trong định nghĩa macro

Một lỗi thông dụng xẩy ra khi định nghĩa Macro đó là sử dụng phép gán để khởi tạo giá trị cho macro.

Ví dụ:

Thay vì phải viết :

#define MAX 100

Thì những lập trình viên sẽ viết

#define MAX = 100

Loại sai lầm không mong muốn này sẽ gây nên ra những lỗi tối nghĩa. Ví dụ vận dụng gây lỗi

for (j=MAX, j > 0; j– )…

Khi đó bộ tiền xử lý sẽ thực thi :

for (j== 100; j > 0, j–) …

Vậy khi đó biểu thức j=100 sẽ trở thành j==100; lúc đó ngữ nghĩa sẽ khác hoàn toàn và là nguyên nhân gây ra lỗi.

3.4. Các yếu tố cần lưu ý

Không in như hàm, những tham số hình thức truyền vào hàm có kiểu, còn tham số của macro không còn kiểu, điều này nghĩa là bộ tiền xử lý sẽ không còn kiểm tra kiểu riêng với tham số của marco.

Ngoài ra thì marco không biến thành xung đột khi lập trình viên sử dụng những tham số trùng tên nhau, với hàm C thì không thể sử dụng những tham số hình thức truyền vào của hàm là trùng tên được;

Ví dụ

#define RECTANGLE_AREA(x, y) ((x) * (y))

Khi gọi hoàn toàn có thể sử dụng

int i = RECTANGLE_AREA(a-1);

Lúc đó

i = ((a-1)*(a-1));

Vậy với hàm trong C thì không như vậy được.

3.5. Chỉ thị bộ tiền xử lý #undef

Sử dụng thông tư bộ tiền xử lý #define để định nghĩa macro. Macro này sẽ có được hiệu lực hiện hành Tính từ lúc lúc nó được định nghĩa đến khi kết thúc file chứa mã nguồn hoặc file header hoặc khi gặp thông tư bộ tiền xử lý #undef. Sử dụng thông tư bộ tiền xử lý #undef để vô hiệu những định nghĩa của những macro, khi đó muốn sử dụng lại macro thì lập trình viên sẽ phải định nghĩa lại.

Ví dụ:

#define WIDTH 80

#define ADD( X, Y ) ((X) + (Y))

.

.

.

#undef WIDTH

#undef ADD

3.6. Sử dụng tên Macro trong chính nội dung định nghĩa của Macro

Với hầu hết những trình biên dịch cũ của C đều không được cho phép tên Macro trong chính nội dung (body toàn thân) của chính macro.

Ví dụ:

Định nghĩa macro sqrt, trong số đó sqrt là tên thường gọi macro và sqrt cũng nằm trong chính body toàn thân của nó.

#define sqrt (x) ( (x < 0) ? sqrt ('x) : sqrt (x) )

Tuy nhiên Chuẩn ANSI tương hỗ cú pháp này. Nhưng xuất hiện chú ý nếu tên macro có trong nội dung của chính macro thì nó sẽ không còn được mở rộng (if a macro name appears in its own definition, it will not be expanded). Điều này tránh khỏi yếu tố mở rộng vô hạn hay là đệ quy vô hạn trong định nghĩa macro.

Ở ví dụ trên, khi sử dụng sqrt như sau:

int y = sqrt ( 5 );

Bộ tiền xử lý sẽ thay thế như sau

int y = ( (5 < 0 ? sqrt (- 5) : sqrt (5 ) );

Bộ tiền xử lý sẽ coi sqrt là một hàm với những tham số truyền vào là -5 để tính kết quả của y. Lưu ý sử dụng tên macro trong chính nội dung của macro là rất nhậy cảm, đặc biệt quan trọng khi tên macro trùng với tên hàm.

3.7. Macro và Hàm

Xét về một khía cạnh nào đó thì Macro và hàm là tương tự như nhau ở đoạn cả hai đều cho sử dụng tên để định danh và đều chứa nội dung được cho phép một tập hợp những xử lý gắn với một trách nhiệm nào đó của bài toán. Do vậy đôi lúc khó quyết định hành động xem sử dụng macro hay hàm thì hiệu suất cao hơn.

Các list sau này tóm tắt những ưu điểm và nhược điểm của macro so với hàm trong C.

Ưu điểm

+ Tốc độ thực thi của Macro nhanh hơn hàm.

+ Số lượng những tham số truyền vào cho macro được kiểm tra để phù phù thích hợp với định nghĩa. Trình biên dịch C cũng thực thi điều này với hàm nếu hàm này được khai báo những nguyên mẫu hàm.

+ Tham số truyền vào cho macro không còn kiểu do vậy khi sử dụng hoàn toàn có thể truyền vào nhiều kiểu tài liệu rất khác nhau.

Nhược điểm

+ Hàm trong C được cho phép gọi những hàm khác và gọi chính nó trong nội dung hàm. Còn macro không được cho phép thực thi điều này. Chính vì vậy với cùng một trách nhiệm, nếu chương trình sử dụng macro thì mã tăng trưởng chương trình sẽ to nhiều hơn so với khi sử dụng hàm.

+ Mặc dù macro có kiểm tra số lượng những tham số truyền vào nhưng không kiểm tra kiểu tài liệu của tham số, điều này dẫn đến khi sử dụng nếu không thận trọng sẽ gây nên lỗi.

+ Sử dụng macro sẽ khó debug hơn vì macro hoạt động và sinh hoạt giải trí ở gian đoạn tiền xử lý.

3.8. Macro được xây dựng sẵn

Chuẩn ANSI phục vụ 5 macro được định nghĩa sẵn của cục tiền xử lý. Mỗi tên của macro được xây dựng sẵn sẽ khởi đầu bởi dấu “__”. Lập trình viên không được sử dụng thông tư bộ tiền xử lý #undif để vô hiệu những macro này.

__LINE__: tin tức về số dòng trong mã chương trình khi dòng lệnh này được gọi, __LINE__ Hữu dụng khi xuất hiện những lỗi thực thi tại dòng lệnh nào đó. Lập trình viên muốn in thông tin về số thứ tự dòng lệnh xuất hiện lỗi này.

__FILE__: Trả về tên file khi file này được gọi

__TIME__: Trả về thời hạn hiện tại tại thời gian biên dịch chương trình theo mẫu hh::mm::ss trong 24h.

__DATE__: Trả về ngày hiện tại tại thời gian biên dịch chương trình theo mẫu mmm dd yyyy trong 24h.

__STDC__: Trả về giá trị 1 nếu trình biên dịch C theo chuẩn ANSI C

Ví dụ

Sử dụng macro được xây dựng sẵn để in những thông tin về số thứ tự dòng, tên file, thời hạn, ngày tháng và thông tin chuẩn ANSI của trình biên dịch

Code minh họa

Hình số 3 : Macro được xây dựng sẵn

Kết quả khi chạy chương trình sẽ in ra những dòng thông tin liên quan tới LINE, TIME, DATE …

Các lập trình viên thường hay sử dụng những macro được tương hỗ sẵn để định nghĩa những file header nhằm mục đích tương hỗ quy trình DEBUG chương trình.

3.9. Toán tử tiền xử lý ##

Trong ANSI sử dụng toán tử tiền xử lý ## để thực thi dán 2 token (ghép 2 token) lại

Ví dụ

#define FILENAME ( extension ) test_ ## extension

Khi đó nếu thực thi

FILENAME( bak )
Thì kết quả trả về là test_bak

Lưu ý : Trong C, những lập trình viên khi sử dụng bộ tiền xử lý thì không thể tự động hóa ghép 2 token (thông tin) lại với nhau một cách thủ công.

Ví dụ

#define FILENAME ( extension ) test_extension

Không hoạt động và sinh hoạt giải trí bởi test_extension sẽ là một định danh duy nhất và phần mở rộng (extension) không xuất hiện ở trong định danh.

Một ví dụ khác sử dụng toán tử tiền xử lý ##

#define READ( type) (file_##type == NULL?

open_##type##_file(), read __ ##type() :

read_##type() )

Trong ví dụ trên khi viết những macro dài quá số lượng giới hạn của dòng thì sử dụng để nối với dòng phía dưới. Macro này được sử dụng để đọc những thành phần trực thuộc file. Nếu file không được mở (ví dụ : file_##type == NULL), macro sẽ mở và gọi đến hàm read_##type(), mặt khác sẽ gọi đến hàm read_##type mà không cần mở tệp.

s = READ( player );

sẽ tiến hành thay thế bằng

s = ( file_player == NULL ? open __ FILE__player(), read_player () : read_player() );

Sẽ tương tự với

if (file_p1ayer == NULL) {

open __ FILE__player();

s = read_p1ayer;

else

s = read_p1ayer;

4. Dịch có Đk

Dịch có Đk được cho phép lập trình viên trấn áp được quy trình thực thi những thông tư của cục tiền xử lý và thực thi dịch mã chương trình. Giống như khi lập trình, C sử dụng cấu trúc if, else … để trấn áp sự thực thi những đoạn mã tương ứng với những Đk logic, bộ tiền xử lý sử dụng những macro #if, #else, #elif, and #endif để thực thi những yếu tố này.

Hình sau mô tả những thông tư bộ tiền xử lý #if, #else…

Hình số 4: Mô tả thông tư dịch có Đk

Ví dụ:

#if x == 1

#undef x

#define x 0

#elif x == 2

#under x

#define x 3

#else

#define y 4

#endif

Trong đoạn mã trên, x là một macro. Nếu nội dung của x là một trong thì x sẽ tiến hành định nghĩa lại, và giá trị nội dung x sẽ là 0. Nếu giá trị nội dung là 2 thì định nghĩa lại x và giá trị nội dung nó là 3. Trong những trường hợp còn sót lại thì định nghĩa y và giá trị nội dung y là 4.

Việc vận dụng những thông tư tiền xử lý có Đk vào nhiều những trường hợp rất khác nhau như tương hỗ xử lý những BUG, Lựa chọn thực thi những hàm gắn với những trình biên dịch rất khác nhau.

Ví dụ : Sử dụng thông tư bộ tiền xử lý có Đk để lựa chọn những hàm xử lý :

#if (_STDC_)

          extern int foot char a, float b );

          extern char *goo( char *string );

#else

          extern int foo();

          extern char *qoo();

#endif

Đoạn mã trên sẽ kiểm tra, nếu trình biên dịch theo chuẩn ANSI thì sử dụng 2 hàm

          extern int foot char a, float b );

          extern char *goo( char *string );

Trong trường hợp ngược lại thì sử dụng 2 hàm:

          extern int foo();

          extern char *qoo();

4.1. DEBUG với dịch có Đk

Dịch có Đk thỉnh thoảng phục vụ mục tiêu xử lý những yếu tố liên quan tới DEBUG của chương trình. Các bộ công cụ lập trình tương hỗ những tính năng rất mạnh mẽ và tự tin để phục vụ cho việc DEBUG, tuy nhiên đôi lúc DEBUG không thành công xuất sắc hoặc gặp trở ngại vất vả, khi đó đôi lúc lập trình viên sẽ nên phải in ra thông tin của một biến rõ ràng trong một vòng lặp while, for hay do-while ví dụ điển hình.

Sử dụng printf kèm theo những thông tư có Đk khi gặp DEBUG và in ra giá trị của một biến.

Ví dụ:

#ifdef DEBUG

  printf(“Variable x = %dn”, x);

#endif

Tất nhiên là DEBUG sẽ phải được định nghĩa bởi #define trước lúc sử dụng thông tư #indef. Khi những lỗi được xử lý xong, thì những bạn hoàn toàn có thể comment lại những #define DEBUG và hàm printf có liên quan. Ngoài cách này ra thì lập trình viên hoàn toàn có thể sử dụng #undef. Tuy nhiên những xử lý này chỉ vận dụng với những chương trình nhỏ. Với những chương trình lớn thì lập trình viên cần tạo ra những file header riêng không liên quan gì đến nhau để xử lý những yếu tố liên quan tới DEBUG.

4.2. Kiểm tra tồn tại của Macro

Chỉ thị dịch có Đk #if, #eif… được cho phép kiểm tra gắn với những Đk, thường những Đk được xác lập bởi giá trị của những biểu thức toán học. Lập trình viên cũng hoàn toàn có thể sử dụng những Đk dịch đặc biệt quan trọng để kiểm tra sự tồn tại hay là không tồn tại của một macro thông qua #ifdef, #ifndef, và #endif.

Ví dụ:

#ifdef TEST

printf( “This is a test.n” ):

#else

printf ( “This is not a test. n” );

#endif

Đoạn mã trên nhằm mục đích mục tiêu kiểm tra macro TEST đã được định nghĩa hay chưa.

Nếu TEST đã được định nghĩa thì sẽ in ra dòng thông báo “This is a test.n” ngược lại thì in ra dòng thông báo “This is not a test. n”

Trong số đó #ifdef TEST là tương tự với :

#if defined TEST

Hoặc

#if defined (TEST)

Về bản chất thì :

#if defined macro_name

Sẽ tương tự với

#ifdef macro_name

Và hòn đảo ngược với đã định nghĩa (defined) thì toàn bộ chúng ta có chưa định nghĩa (!defined)

#if !defined macro_name

Tương đương với

#ifndef macro_name

Ví dụ:

Sử dụng !defined để định nghĩa Macro FALSE có mức giá trị là 0.

#if !FALSE

# define FALSE 0

#endif

Để tránh việc sử dụng !FALSE thì toàn bộ chúng ta hoàn toàn có thể sử dụng #ifndef khi đó đoạn mã trên sẽ tiến hành viết thành:

#ifndef FALSE

# define FALSE 0

#elif FALSE

# undef FALSE

# define FALSE 0

#endif

4.3 Chỉ thị #error
Chỉ thị #error được cho phép đưa ra thông báo lỗi trong quy trình dịch chương trình. Dòng thông báo gắn với thông tư #error sẽ gửi ra thiết bị thông báo lỗi chuẩn. Thông thường nó được sử dụng gắn với những #if… để kiểm tra một Đk nào đó.

Ví dụ:

#if INTSIZE < 16

# error INTSIZE too small

#endif

Thực hiện dịch bằng câu lệnh

Nội dung được ghi vào file ví dụ test.c hoặc một file header, tiếp theo đó trong test.c sẽ tiến hành #include.

cc -D INTSIZE=8 test.c

Khi này sẽ nhận được tin báo

INTSIZE too small

5. Điều khiển dòng

Theo chuẩn ANSI, định nghĩa thông tư tiền xử lý #line thiết lập số thứ tự dòng hiện thời của câu lệnh được thực thi hiện tại của tệp mã nguồn và tên tệp mã nguồn.

Hình số 5: Cú pháp thông tư #line

Cú pháp

#line number_row

Với number_row là số dòng

Giả sử ta có câu lệnh:

printf( “Current line: %dn”, __LlNE_);

Khi đó kết quả in ra là Current line: 5

Điều đó nghĩa là loại lệnh thực thi hiện tại sẽ có được thứ tự 5

Sau đó ta tương hỗ update câu lệnh

printf( “Current line: %dn”, __LlNE_);

#line 100

printf( “Current line: %dn”, __LlNE_);

Khi đó nó sẽ in ra thông tin là:

Current line: 5

Current line: 100

Vì khi gặp câu lệnh #line 100, thì trình biên dịch sẽ chuyển câu lệnh thực thi dòng hiện tại về vị trí là 100. Do vậy câu lệnh sau sẽ in ra là 100 chứ không phải là 7.

Ví dụ code minh họa

Hình số 6: Minh họa thông tư #line

6. Chỉ thị #pragma

Chỉ thị tiền xử lý #pragma thực thi những trách nhiệm rõ ràng và để phục vụ những thông tin tương hỗ update cho trình biên dịch C.

Cú pháp

#prama token_name

Trong số đó : token_name có chứa 6 giá trị như : startup, exit, warn…

Ví dụ:

#include

int display();

#pragma startup display

#pragma exit display

int main()

  printf(“nI am in main function”);

  return 0;

int display()

  printf(“nI am in display function”);

  return 0;

Khi gặp #pragma startup display thì trước lúc thực thi hàm main nó sẽ thực thi hàm display.

Khi gặp #pragma exit display thì trước lúc kết thúc chương trình nó sẽ gọi đến hàm display.

Reply
1
0
Chia sẻ

4595

Clip Bộ tiền xử lý c được chỉ định bằng ký hiệu: ?

Bạn vừa đọc nội dung bài viết Với Một số hướng dẫn một cách rõ ràng hơn về Video Bộ tiền xử lý c được chỉ định bằng ký hiệu: tiên tiến và phát triển nhất

Chia Sẻ Link Download Bộ tiền xử lý c được chỉ định bằng ký hiệu: miễn phí

Heros đang tìm một số trong những ShareLink Download Bộ tiền xử lý c được chỉ định bằng ký hiệu: miễn phí.

Hỏi đáp vướng mắc về Bộ tiền xử lý c được chỉ định bằng ký hiệu:

Nếu sau khi đọc nội dung bài viết Bộ tiền xử lý c được chỉ định bằng ký hiệu: vẫn chưa hiểu thì hoàn toàn có thể lại Comment ở cuối bài để Mình lý giải và hướng dẫn lại nha
#Bộ #tiền #xử #lý #được #chỉ #định #bằng #ký #hiệu