Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 19.222 phút đọc

define và macro đối tượng

Sau bài này bạn sẽ làm được

  • Định nghĩa hằng số bằng define và hiểu nó chỉ là thay thế văn bản
  • So sánh macro với const và enum trên bốn tiêu chí
  • Biết phạm vi của macro là từ chỗ định nghĩa tới cuối đơn vị dịch
  • Dùng undef đúng lúc và biết vì sao ít khi cần tới

Macro đối tượng là dạng đơn giản nhất của #define: một cái tên, và đoạn văn bản thay vào chỗ cái tên đó. Đơn giản tới mức nhiều người dùng nó cho việc mà C đã có công cụ tốt hơn.

#Định nghĩa và thay thế

#define TEN  noi_dung_thay_the

#define PI          3.14159265358979
#define BO_DEM_CO   1024
#define TEN_APP     "Quan ly sinh vien"
#define GO_LOI                          /* khong co gia tri */
Macro đối tượng
Macro không có tham số. Mỗi lần tên nó xuất hiện như một token riêng trong mã, preprocessor thay bằng phần văn bản đứng sau tên trong dòng #define.
terminal
cat thu.c
#define BO_DEM_CO 1024
#define TEN_APP "Quan ly"

char bo_dem[BO_DEM_CO];
const char *ten = TEN_APP;
int nua = BO_DEM_CO / 2;
gcc -E -P thu.c
char bo_dem[1024];
const char *ten = "Quan ly";
int nua = 1024 / 2;

#Phạm vi của macro

void f(void) {
    #define TAM 10          /* dinh nghia ben trong ham */

    int a = TAM;
}

void g(void) {
    int b = TAM;            /* VAN DUNG DUOC: macro khong theo khoi lenh */
}

#Macro, const hay enum

Tiêu chí#defineconstenum
Có kiểuKhôngCóCó, kiểu int
Trình gỡ lỗi thấy được tênKhôngCóCó
Dùng làm kích thước mảngĐượcKhông trong CĐược
Dùng trong nhãn caseĐượcKhôngĐược
Tuân theo phạm vi khốiKhôngCóCó
Dùng được cho số thựcĐượcĐượcKhông
Dùng được cho chuỗiĐượcĐượcKhông

#undef và định nghĩa lại

#define TAM 100
/* ... dung TAM ... */
#undef TAM              /* huy dinh nghia */

int TAM = 5;            /* gio hop le tro lai */

#Quy ước đặt tên

LoạiKiểu tênVí dụ
Macro thườngCHU_HOA_GACH_DUOIBO_DEM_CO, PHIEN_BAN
Macro của một moduleTIEN_TO_TENSV_MSSV_CO, QL_TOI_DA
Header guardTEN_TEP_HSINHVIEN_H, QUANLY_LOI_H
Macro nội bộ, không phải giao diệnTIEN_TO_GACH_DUOI_TENSV_NOI_BO_KIEM

Bộ hằng số của một module trông như thế nào

sinhvien.h
#ifndef SINHVIEN_H
#define SINHVIEN_H

/* Kich thuoc: dung enum vi chung la kich thuoc mang */
enum {
    SV_MSSV_CO = 16,
    SV_TEN_CO  = 64,
    SV_LOP_CO  = 16,
    SV_SO_MON  = 5,
};

/* Nguong diem: dung enum vi chung la so nguyen nhan 100 */
enum {
    SV_NGUONG_XUAT_SAC = 900,
    SV_NGUONG_GIOI     = 800,
    SV_NGUONG_KHA      = 650,
    SV_NGUONG_TB       = 500,
};

/* Phien ban dinh dang tep: dung define vi #if can thay */
#define SV_PHIEN_BAN 1

#endif /* SINHVIEN_H */

Tự làm thử

  1. Định nghĩa #define N = 10; có dấu bằng và dấu chấm phẩy, dùng nó làm kích thước mảng, rồi đọc thông báo lỗi.
  2. Định nghĩa #define max(a,b) ... chữ thường rồi khai báo một biến tên max, xem chuyện gì xảy ra.
  3. Thử const int N = 10; rồi int a[N]; ở phạm vi tệp và giải thích lỗi.
  4. Viết mẫu #ifndef ... #define ... #endif cho một hằng số cấu hình, rồi ghi đè nó bằng cờ -D.
  5. Đổi một nhóm bốn #define số nguyên thành một khối enum và xác nhận chương trình vẫn chạy như cũ.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • #define chỉ là thay thế văn bản, không có dấu bằng và không có dấu chấm phẩy.
  • Macro sống từ dòng định nghĩa tới cuối đơn vị dịch, không tuân theo phạm vi khối lệnh nào.
  • Vì vậy macro phải viết hoa hết, và tên bắt đầu bằng gạch dưới là của thư viện chứ không phải của bạn.
  • const trong C không phải hằng số biên dịch, nên kích thước mảng và nhãn case phải dùng enum hoặc #define.
  • Quy tắc thực dụng: enum cho số nguyên, const cho số thực và chuỗi, #define khi preprocessor phải nhìn thấy.