sách gpt4 ăn đã đi

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

In lại Tác giả: qq735679552 Thời gian cập nhật: 27-09-2022 22:32:09 27 4
mua khóa gpt4 giày nike

CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.

Bài blog CFSDN này về quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm tới bài viết này thì nhớ like nhé.

Sơ đồ này mô tả các bước tổng thể từ tệp nguồn đến tệp thực thi:

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Hình ảnh này cho thấy các bước chung.

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Từ mã đến môi trường chạy, trình biên dịch cung cấp môi trường dịch thuật. Trong một chương trình, sẽ có nhiều tệp và mỗi tệp nguồn sẽ được trình biên dịch xử lý riêng.

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Biên dịch trước: 1. Sao chép tất cả nội dung và chức năng thư viện có trong các tệp tiêu đề, chẳng hạn như #include. 2. Xóa các nhận xét trong mã 3. Thay thế tất cả các ký hiệu được xác định bởi #define vào mã cho các hướng dẫn tiền xử lý.

Biên dịch: Dịch mã C thành mã hợp ngữ 1. Phân tích cú pháp (xác định xem ngôn ngữ có lỗi ngữ pháp nào ngăn cản việc biên dịch) 2. Phân tích từ vựng 3. Phân tích ngữ nghĩa (phân tích ý nghĩa từng câu mã) 4. Tóm tắt ký hiệu (sẽ biên dịch toàn bộ mã Ký hiệu toàn cầu trong chương trình được tóm tắt).

Hội 1, tạo thành bảng ký hiệu.

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Có một chương trình gồm hai tệp test.c và add.c, trong test.c.

extern int add(int x, int y);//Khai báo tham chiếu đến hàm và tìm hàm trong các file khác.

Trong quá trình hợp ngữ, mỗi tệp sẽ có một bảng ký hiệu hàm tham số chính thức, nhưng extern sẽ không tạo thành dấu địa chỉ, chỉ là 0x00.

Liên kết: Hợp nhất bảng phân đoạn Hợp nhất và định vị lại các bảng ký hiệu Kiểm tra từng hàm và câu định nghĩa của nó.

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

  。

Các hằng số được đặt tên#define

xác định các chỉ thị tiền xử lý.

#define Thay thế MACRO Nội dung thay thế macro chỉ thị tiền xử lý.

Ví dụ, macro chỉ đóng vai trò thay thế và không tạo ra bất kỳ thao tác nào trong quá trình thay thế.

#define SUM 2+2int num = SUM * SUM;

Những người không hiểu có thể nghĩ rằng đó là num=44; Tuy nhiên, nó thực sự thay thế num=2+22+2; Điều này có nghĩa là macro chỉ đóng vai trò thay thế.

Hãy giới thiệu một khái niệm nguyên tắc.

Mã thông báo Từ quan điểm kỹ thuật, phần thân thay thế của macro có thể được coi là chuỗi mã thông báo. chứ không phải là một chuỗi ký tự. Trong mã thông báo tiền xử lý C là các "từ" riêng lẻ trong phần thân thay thế của định nghĩa macro, với khoảng trắng ngăn cách các từ. Ví dụ:

#define FOUR 2*2#define FOURS 2 * 2

Đối với hai phần này, bộ tiền xử lý phụ thuộc vào việc bộ tiền xử lý coi phần thân thay thế này là gì. Nếu là chuỗi ký tự thì khoảng trắng này cũng sẽ là một phần của chuỗi. Nhưng nếu đó là chuỗi mã thông báo, dấu cách sẽ được coi là dấu phân cách, có nghĩa tương tự như 2*2. Nói tóm lại, nó phụ thuộc vào quy tắc của trình biên dịch. Để tóm tắt.

Nếu trình biên dịch hiểu rằng phần thân thay thế là một chuỗi ký tự thì khoảng trắng sẽ được coi là một phần của chuỗi. Nếu trình biên dịch hiểu nó là một chuỗi mã thông báo thì khoảng trắng sẽ chỉ được coi là dấu phân cách và không có tác dụng. Khoảng trắng không phải là một phần của phần thân thay thế và 2 nhân 2 có cùng ý nghĩa.

  。

định nghĩa lại hằng số

Giả sử bạn đặt MAX thành 30 và xác định lại nó thành 10 trong tệp. Quá trình này được gọi là xác định lại các hằng số, nhưng các tiêu chuẩn khác nhau có các quy tắc khác nhau. Một số cho phép xác định lại nhưng sẽ cảnh báo bạn. Tiêu chuẩn ANSI được thông qua và việc xác định lại chỉ được phép nếu định nghĩa cũ và mới hoàn toàn giống nhau. Giống hệt nhau có nghĩa là các mã thông báo thay thế phải hoàn toàn giống nhau và theo cùng thứ tự.

#xác định MAX 2 * 3#xác định MAX 2 * 3

Điều này được cho phép.

#xác định MAX 2 * 3#xác định MAX 2*3

Điều này không đáp ứng được tiêu chuẩn đó. (Mặc dù không biết công dụng của việc định nghĩa lại chuẩn này là gì nhưng mình cũng tương đối giỏi) Lưu ý: Theo lời khuyên của một ông lớn thì loại code này rất tai hại và rất tệ, và tốt nhất là không sử dụng nó.

  。

Sử dụng tham số trong #define

Trong #define, bạn cũng có thể tạo các macro giống hàm có giao diện và hoạt động giống hàm. Macro có chức năng có thể đạt được hiệu quả của một số chức năng.

#define VUÔNG(X) X*Xmul=VUÔNG(2);

Khá giống với các cuộc gọi hàm. Tốt nhất bạn nên sử dụng đủ dấu ngoặc đơn để đảm bảo hoạt động chính xác và tính liên kết.

mul=BÌNH PHƯƠNG(x++)

Điều này sẽ khiến hoạt động không đạt yêu cầu.

Tạo một chuỗi có tham số macro: #operator.

#define PSQRA(X) printf("X là %d\n",((X)*(X));#define PSQRB(X) printf("#X" là %d\n",((X)*(X));

Hai cái này có thể in các hiệu ứng khác nhau. #Là toán tử tiền xử lý, nó có thể chuyển đổi mã thông báo thành chuỗi. Nếu X là tham số macro thì #X là tên tham số chính thức của chuỗi "X".

Điều này được gọi là xâu chuỗi.

int y=50;PSQRA(y)X là 2500PSQRB(Y)y là 2500PSQRA(2+4)X là 36PSQRB(2+4)2+4 là 36

Đó là sự khác biệt.

  。

Chất kết dính tiền xử lý: toán tử ##

Toán tử # có thể được sử dụng để thay thế macro và toán tử ## cũng có thể được sử dụng.

#define NUMBER(n) X##nNUMBER(4) có thể được mở rộng thành x4

Ví dụ.

#include #define XNAME(N) x##N#define PRINT(N) pritnf("x"#N"=%d\n",x##N);int main(void){ int XNAME(1) = 10;//x1=10 int XNAME(2) = 20;//x2=10 int x3 = 0; PRINT(1);//printf("x1=%d",x1); PRINT(2);//printf("x2=%d",x2); PRINT(3);//printf("x3=%d",x3);}

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

  。

Macro tham số biến: ... và _ _ VAG_ARGS_ _

Một số hàm có thể chấp nhận số lượng đối số thay đổi (nghĩa là không có số lượng đối số cố định được truyền, chẳng hạn như printf() và scanf()). Macro cũng có thể có khả năng này.

#define PR(...) printf(_ _VAG_ARGS_ _)PR("XIN CHÀO THẾ GIỚI");//printf("XIN CHÀO THẾ GIỚI");PR("x1=%d,x2=%d",10,20);//printf(""x1=%d,x2=%d",10,20);

Tương đương với hiệu ứng này. Hình elip chỉ có thể thay thế tham số macro cuối cùng. Bạn không thể thêm các tham số khác vào dấu ba chấm.

#xác định PR(x,...,y) #x #_ _VAG_ARGS_ _ #y

không được phép.

  。

Macro và chức năng

Có khá nhiều macro có thể có tác dụng tương tự như hàm, nhưng bạn nên lựa chọn như thế nào? Macro và chức năng có thể đạt được hiệu quả tương tự. Macro đơn giản hơn hàm, đồng thời, thời gian tiêu tốn trong trình biên dịch ít hơn nhiều so với hàm. Tuy nhiên, nếu không cẩn thận, một số tác dụng phụ có thể xảy ra, dẫn đến kết quả khó lường. Sự so sánh giữa macro và chức năng thực chất là sự so sánh giữa thời gian và không gian.

Macro sẽ tạo mã nội tuyến khi được biên dịch trước, nghĩa là chúng sẽ thay thế các câu lệnh được tạo trong chương trình. Nếu gọi 20 lần thì sẽ có 20 dòng code được chèn vào chương trình.

Nhưng nếu hàm được gọi 20 lần thì sẽ chỉ có một bản sao của hàm, tiết kiệm được một lượng không gian đáng kể. Nhưng khi thực thi một hàm, nó cần được gọi, thực thi lại và trả về lần nữa, việc này mất nhiều thời gian hơn so với việc chèn một câu lệnh nội tuyến bằng macro.

Macro cũng có nhược điểm so với chức năng.

  • Độ dài mã tăng khi macro lớn hơn.
  • Không thể gỡ lỗi macro (việc thay thế đã được hoàn thành trong quá trình biên dịch trước) và có thể xảy ra sự cố.
  • Vì macro không yêu cầu kiểu nên chúng sẽ lỏng lẻo (đây cũng là một lợi ích cho các hàm. Việc truyền tham số hàm sẽ yêu cầu kiểu tham số, trong khi macro sẽ chỉ coi tham số là chuỗi, miễn là chúng là kiểu int hoặc float)
  • Macro có thể gây ra các vấn đề về quyền ưu tiên của người vận hành và khiến các thao tác không thể đoán trước được.

Sử dụng nó theo tình hình. Nếu sử dụng macro dễ gây ra tác dụng phụ, hãy gọi hàm thay thế.

Nhưng có một số điều cần ghi nhớ.

1. Hãy nhớ rằng không được phép có khoảng trắng trong tên macro nhưng được phép có khoảng trắng trong chuỗi thay thế. ANSI C cho phép khoảng trắng trong danh sách tham số.

2. Sử dụng dấu ngoặc đơn để bao quanh các tham số và phần thân thay thế của macro và mở rộng chúng một cách chính xác để ngăn ngừa tác dụng phụ.

3. Các hằng số macro thường được biểu thị bằng chữ in hoa và các hàm macro thường không được biểu thị bằng tất cả các chữ cái viết hoa.

4. Nếu bạn sử dụng macro để tăng tốc chức năng, trước tiên bạn phải xác định xem có khoảng cách giữa macro và chức năng hay không. Hơn nữa, nếu chỉ sử dụng một lần thì sẽ không có tác dụng gì nhiều trong việc tăng tốc. Sử dụng tốt nhất trong nhiều tổ.

  。

chỉ thị tiền xử lý

Khi trình biên dịch gặp lệnh #include, nó sẽ xem tên tệp sau và thêm nội dung vào tệp hiện tại.

#include //Tìm tệp thư mục hệ thống #include "mtfile.h"//Tìm thư mục làm việc hiện tại #include "/usr/biff/file.h"//Tìm thư mục /usr/biff/

Các hệ thống khác nhau có các quy tắc khác nhau, nhưng các quy tắc cho <> và "" vẫn không thay đổi.

Thông qua tham chiếu của tệp tiêu đề, chúng ta có thể sử dụng nhiều chức năng khác nhau. Có các khai báo về các chức năng khác nhau trong tệp tiêu đề. Sau đó gọi nguyên mẫu của hàm thông qua tệp thư viện.

  。

chỉ thị #undef

Bạn có thể sử dụng lệnh này để đi tới macro được xác định #define trước đó.

#include #define MAX 10#undef MAXint main(void){ printf("%d", MAX);}

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Báo cáo lỗi trực tiếp #undef có thể bị hủy. Định nghĩa của một macro nhất định có thể được sử dụng để ngăn chặn việc một macro nhất định được xác định nhiều lần và gây ra lỗi.

  。

Được xác định từ quan điểm của bộ tiền xử lý C

Bộ tiền xử lý tuân theo các quy tắc tương tự khi xử lý số nhận dạng. Khi bộ tiền xử lý tìm thấy một mã định danh, nó sẽ coi nó là được xác định hoặc không được xác định. Định nghĩa ở đây được xác định bởi bộ tiền xử lý. Nếu mã định danh được xác định bằng định nghĩa và không bị hủy bởi undef thì nó được xác định. Nếu một biến toàn cục được xác định, nó sẽ không được xác định (đối với bộ tiền xử lý).

Phạm vi của macro được xác định bởi #define bắt đầu từ đầu tệp và mở rộng đến cuối tệp hoặc được xác định khi gặp #undef. Nếu được sử dụng trên các tệp, vị trí được sử dụng phải nằm sau tệp được tham chiếu bởi #include. .

  。

biên dịch có điều kiện

Nó có ý nghĩa tương tự như câu phán đoán có điều kiện.

#ifdef, #else, #endif 。

Đưa ra một ví dụ.

#include #xác định MAX 10#undef MAX#ifdef MAX #include  #xác định MIN 10#endif // int main(void){ printf("%d", MIN);}

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Kết quả là thế này. Nhưng mặt nạ #undef.

#include #định nghĩa MAX 10//#undef MAX#ifdef MAX #include  #định nghĩa MIN 10#endif // int main(void){ printf("%d", MIN);}

Quá trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C

Nó hoạt động. Hướng dẫn biên soạn có điều kiện tương tự như các câu lệnh phán đoán có điều kiện. Tuy nhiên, câu lệnh phán đoán có điều kiện là để đánh giá xem có nên thực hiện hay không và lệnh biên dịch có điều kiện thứ hai là để đánh giá xem có nên biên dịch trước hay không. #endif được sử dụng để kết thúc phạm vi của lệnh và giới thiệu một lệnh khác.

#ifndef GỠ LỖI.

Nếu DEBUG không được xác định, quá trình biên dịch sẽ được thực hiện, nếu được xác định, quá trình biên dịch sẽ không được thực hiện.

Ngoài ra còn có những hướng dẫn này rất gần với các tuyên bố phán đoán có điều kiện.

#nếu ,#nếu không ,#nếu không 。

#if và #elif tương tự như if và else if. Nhưng chúng được theo sau bởi một biểu thức hằng số nguyên. 0 là sai và khác 0 là đúng để xác định có nên biên dịch trước hay không.

Hướng dẫn biên dịch có điều kiện có thể được sử dụng để ngăn chặn việc gọi một số tệp nhất định nhiều lần và gây ra sự cố.

#ifndef _FILE_H#xác định nội dung tệp _FILE_H. . #endif

Hoặc sử dụng trực tiếp.

#pragma một lần//Nó đảm bảo rằng tệp chỉ được sử dụng một lần

  。

hàm offset

size_t offsetof( structName, memberName );

Được sử dụng để đo độ lệch của các bộ phận kết cấu so với vị trí ban đầu của chúng.

hoàn thành.

#define OFFSETOF(structName,memberName) (int)&(((struct structName*)0)->memberName)

Từ địa chỉ 0, bắt đầu truy cập thành viên, sau đó lấy địa chỉ và buộc nó thành số nguyên.

Trên đây là chi tiết về quy trình tiền xử lý, định nghĩa và biên dịch có điều kiện của lập trình ngôn ngữ C. Để biết thêm thông tin về tiền xử lý ngôn ngữ C, vui lòng theo dõi các bài viết liên quan khác của tôi! .

Liên kết gốc: https://blog.csdn.net/weixin_52199109/article/details/115048443.

Cuối cùng, bài viết về quy trình tiền xử lý, xác định và biên dịch có điều kiện của lập trình ngôn ngữ C kết thúc tại đây. Nếu bạn muốn biết thêm về quy trình tiền xử lý, xác định và biên dịch có điều kiện của lập trình ngôn ngữ C, vui lòng tìm kiếm bài viết CFSDN. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .

27 4 0
qq735679552
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress