Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Preprocessor ใน C/C++: #define, #include, Conditional Compilation

Preprocessor (ตัวประมวลผลก่อนคอมไพล์) ทำงานก่อน Compilation จริงๆ จัดการ Directives เริ่มต้นด้วย `#` ไม่ใช่ C++ Statements (ไม่มี Semicolon)

Directives หลัก

1. #include: รวม Header File


#include <iostream>      // System Header (Angle Brackets)
#include "my_header.h"   // User Header (Quotes)

2. #define: Macro Definition

  • Object-like Macro: #define PI 3.14159
  • Function-like Macro: #define MAX(a,b) ((a)>(b)?(a):(b))
  • Token Pasting (##): #define CONCAT(a,b) a##b
  • Stringizing (#): #define STR(x) #x

3. Conditional Compilation


#ifdef DEBUG
    std::cerr << "Debug: x = " << x << '\n';
#endif

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

#if VERSION >= 2
    // Code for Version 2+
#else
    // Legacy Code
#endif

// Comment out Block
#if 0
    legacy_code();
#endif

4. #error, #warning, #pragma


#error "Unsupported Platform"
#warning "Deprecated API used"
#pragma once           // Include Guard (Modern)
#pragma pack(push, 1)  // Struct Packing

ตัวอย่างครบ: Debug Macro

#include <iostream>

#define DEBUG 1
#define MIN(a,b) (((a)<(b)) ? (a) : (b))

int main() {
    int i = 100, j = 30;
    
    #ifdef DEBUG
        std::cerr << "Trace: Inside main\n";
    #endif
    
    #if 0
        std::cout << "This is disabled\n";
    #endif
    
    std::cout << "Min: " << MIN(i, j) << '\n'; // 30
    
    #ifdef DEBUG
        std::cerr << "Trace: Exiting main\n";
    #endif
}

ผลลัพธ์


Trace: Inside main
Min: 30
Trace: Exiting main

Include Guards vs #pragma once


// Traditional Include Guard
#ifndef MY_HEADER_H
#define MY_HEADER_H
// ... declarations
#endif

// Modern (Supported by all major compilers)
#pragma once
// ... declarations

ข้อเสียของ Macros

  • No Type Safety (Text Substitution)
  • No Scope (Global Pollution)
  • Side Effects: MAX(i++, j++) → Increment สองครั้ง
  • Debugging ยาก (ไม่เห็นใน Symbol Table)

Modern C++ Replacements

MacroModern Alternative
Constantsconstexpr / const Variables
Function-like Macrosinline Functions / constexpr Functions
Type Aliasesusing / typedef
Conditional Compilationif constexpr (C++17) / Concepts (C++20)

สรุป

Preprocessor ทรงพลังแต่อันตราย ใช้ #include, #define (Constants), Conditional Compilation ให้เหมาะสม หลีกเลี่ยง Function-like Macros ใช้ `inline/constexpr` Functions แทน C++17 `if constexpr` ลดความต้องการ Preprocessor Conditionals ได้มาก