Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình C

Các lệnh tiền xử lý (Preprocessor Commands) trong C

Tiền xử lý (Preprocessor) là gì?

Chương trình chạy trước compiler, xử lý các chỉ thị bắt đầu bằng #. Không hiểu C, chỉ xử lý văn bản.

3 nhóm chính

  1. Macro substitution - Thay thế macro
  2. File inclusion - Nhúng file
  3. Conditional compilation - Biên dịch điều kiện

1. Macro Substitution Directives

#define - Định nghĩa macro


// Hằng số
#define PI 3.14159
#define MAX_SIZE 100
#define TEN_CHUONG_TRINH "MyApp"

// Macro hàm (function-like)
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define BINH_PUONG(x) ((x) * (x))
#define IN_LOG(fmt, ...) printf("[LOG] " fmt "\n", ##__VA_ARGS__)

// Macro nhiều dòng (dùng \)
#define KHOI_TAO_MANG(arr, size) \
    do { \
        for (int i = 0; i < size; i++) arr[i] = 0; \
    } while(0)

#undef - Hủy macro


#define DEBUG 1
// ... code dùng DEBUG ...
#undef DEBUG
// DEBUG không còn hiệu lực

Ví dụ chương trình Macro

#include <stdio.h>

#define WAIT getchar()
#define IN_CHUOI(s) printf("%s\n", s)

int main() {
    IN_CHUOI("Xin chao");
    IN_CHUOI("Tien xu ly macro");
    WAIT;
    return 0;
}

2. File Inclusion Directives

#include - Nhúng file


// Thư viện hệ thống - tìm trong include path
#include 
#include 

// File dự án - tìm trong thư mục hiện tại trước
#include "myheader.h"
#include "utils/string.h"

3. Conditional Compilation (Biên dịch điều kiện)

#ifdef / #ifndef / #endif


#define DEBUG 1

#ifdef DEBUG
    printf("Debug: x = %d\n", x);
#endif

#ifndef NDEBUG
    assert(x > 0);
#endif

#if / #elif / #else / #endif


#define VERSION 2

#if VERSION == 1
    printf("Phien ban 1\n");
#elif VERSION == 2
    printf("Phien ban 2 - Moi\n");
#else
    printf("Phien ban khac\n");
#endif

#error / #warning


#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
#error "Can C99 or later"
#endif

#if defined(__linux__)
#warning "Chay tren Linux, kiem tra path separator"
#endif

Defined operator


#if defined(DEBUG) && defined(VERBOSE)
    // Cả DEBUG và VERBOSE đều định nghĩa
#endif

#if defined(WIN32) || defined(_WIN32)
    // Windows
#endif

Các Macro định sẵn (Predefined Macros)

Macro Giá trị
__FILE__Tên file nguồn hiện tại (string)
__LINE__Số dòng hiện tại (int)
__DATE__Ngày compile "Mmm dd yyyy"
__TIME__Giờ compile "hh:mm:ss"
__func__Tên hàm hiện tại (C99)
__STDC__1 nếu tuân thủ ANSI C
__STDC_VERSION__Phiên bản C (199409L, 199901L, 201112L...)

Chương trình demo Predefined Macros

#include <stdio.h>

void hamDemo() {
    printf("File: %s\n", __FILE__);
    printf("Dong: %d\n", __LINE__);
    printf("Ngay: %s\n", __DATE__);
    printf("Gio: %s\n", __TIME__);
    printf("Ham: %s\n", __func__);
}

int main() {
    hamDemo();
    return 0;
}

Kết quả


File: main.c
Dong: 5
Ngay: Dec 15 2024
Gio: 14:30:25
Ham: hamDemo

Stringizing (#) và Token Pasting (##)


// Stringizing: biến tham số thành chuỗi
#define TO_STRING(x) #x
printf("%s\n", TO_STRING(Hello));  // "Hello"

// Token Pasting: ghép token
#define CONCAT(a, b) a##b
int xy = 100;
printf("%d\n", CONCAT(x, y));  // 100

// Ứng dụng: Tạo tên biến/hàm tự động
#define DECLARE_ARRAY(name, size) int name##_arr[size] = {0}
DECLARE_ARRAY(student, 50);  // → int student_arr[50] = {0};

Best Practice

  • Dùng const / enum thay macro cho hằng số (type safety, debug)
  • Dùng inline thay macro hàm
  • Luôn bao tham số macro trong ngoặc: #define MAX(a,b) ((a)>(b)?(a):(b))
  • Dùng do { ... } while(0) cho macro nhiều câu lệnh
  • Include guard cho mọi header
  • Tránh macro phức tạp, khó debug