Chuyển tới nội dung chính

Các chỉ thị tiền xử lý trong C/C++

Chỉ thị tiền xử lý (preprocessor directives) trong C/C++ là những lệnh bắt đầu bằng dấu # và được xử lý trước khi trình biên dịch thực sự biên dịch mã nguồn. Chúng không tạo ra mã máy, mà điều khiển cách mã nguồn được biên dịch, bao gồm việc nhúng file, định nghĩa macro, hoặc kiểm soát điều kiện biên dịch.

Nhóm chèn và điều khiển mã nguồn

#include
Dùng để chèn nội dung của một file khác vào file hiện tại.

#include <iostream>      // thư viện chuẩn
#include "mylib.hpp" // file do người dùng định nghĩa

#define#undef
Dùng để định nghĩa hoặc hủy định nghĩa một macro.

#define PI 3.14
#define DEBUG
#undef DEBUG

Nhóm điều kiện biên dịch (Conditional Compilation)

#if, #ifdef, #ifndef, #elif, #else, #endif
Cho phép biên dịch có điều kiện

#define DEBUG

#ifdef DEBUG
std::cout << "Debug mode" << std::endl;
#else
std::cout << "Release mode" << std::endl;
#endif

Nhóm điều khiển biên dịch hoặc hệ thống

#pragma
Chỉ thị đặc biệt gửi đến trình biên dịch, mỗi trình biên dịch sẽ có các #pragma riêng.

Bỏ qua cảnh báo (với clang)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
for (size_t i = 0; i < n; i++) { arr[i] = static_cast<int>(i); }
for (size_t i = 0; i < n; i++) { std::cout << arr[i] << " "; }
#pragma clang diagnostic pop
Chỉ định nạp header 1 lần duy nhất
#pragma once
Điều khiển căn lề struct (packing)
#pragma pack(push, 1)
struct Packet {
char a;
int b;
};
#pragma pack(pop)
Liên kết với user32.lib
#pragma comment(lib, "user32.lib") // Liên kết với user32.lib
  • Tự động báo cho linker liên kết với user32.lib, tương đương với việc thêm user32.lib vào tùy chọn linker trong lệnh biên dịch hoặc file cấu hình build (như CMakeLists.txt)
  • Chỉ thị chỉ dành riêng cho trình biên dịch clang-cl, cl (MSVC)
  • Khi dùng #pragma comment(lib,... trong mã nguồn, bạn không cần khai báo thư viện tương ứng trong lệnh liên kết khi biên dịch.
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
  • Chỉ định cờ cho trình liên kết mà không cần ghi cờ tương ứng trong lệnh biên dịch.
  • Chỉ thị chỉ dành riêng cho trình biên dịch clang-cl, cl (MSVC)

#error#warning
Sinh lỗi hoặc cảnh báo trong quá trình biên dịch.

#ifndef VERSION
#error "Macro VERSION chưa được khai báo!"
#endif

#line
Dùng để thay đổi số dòng được báo lỗi trong compiler.

#line 100 "myfile.cpp"

lưu ý
  • Dùng #pragma once thay include guard (#ifndef) để ngắn gọn.
  • Tránh macro phức tạp; ưu tiên inline hoặc constexpr trong C++.
  • Kiểm tra tính tương thích của #pragma với trình biên dịch (ví dụ: #pragma pack được hỗ trợ, nhưng một số chỉ thị khác có thể không).