0Pricing
C Academy · บทเรียน

การคอมไพล์แบบมีเงื่อนไข

ifdef และมาโคร

การคอมไพล์แบบมีเงื่อนไข เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

ตัวประมวลผลล่วงหน้า

ก่อนที่คอมไพเลอร์จะเห็นโค้ดของคุณ ตัวประมวลผลล่วงหน้าจะทำงานก่อน โดยจัดการทุกบรรทัดที่เริ่มต้นด้วย # ได้แก่ การรวมไฟล์ มาโคร และเงื่อนไข

การคอมไพล์แบบมีเงื่อนไขช่วยให้คุณรวมหรือตัดบล็อกโค้ดออกตามเงื่อนไขที่ประเมินในขั้นตอนนี้ ทำให้สร้างโปรแกรมคนละรูปแบบจากซอร์สเดียวกันได้

การกำหนดมาโคร

#define ใช้สร้างมาโคร หากไม่กำหนดค่าให้ มาโครนั้นจะเป็นเพียงแฟล็กที่คุณตรวจสอบภายหลังได้

มาโครรูปแบบอ็อบเจ็กต์จะแทนที่ชื่อด้วยข้อความ ส่วนแฟล็กจะทำหน้าที่เพียงระบุว่ามีการตั้งค่าไว้

#define MAX_USERS 100   /* value macro */
#define DEBUG          /* flag macro */

ifdef และ ifndef

#ifdef NAME จะคงบล็อกไว้เฉพาะเมื่อมีการกำหนด NAME แล้ว ส่วน #ifndef จะคงบล็อกไว้เฉพาะเมื่อยังไม่ได้กำหนดชื่อดังกล่าว

ในที่นี้ คำสั่งพิมพ์ข้อมูลการแก้จุดบกพร่องจะมีอยู่เฉพาะในบิลด์สำหรับแก้จุดบกพร่องเท่านั้น หากไม่ได้กำหนด DEBUG คอมไพเลอร์จะไม่เห็นบรรทัดนั้นเลย

#include <stdio.h>
#define DEBUG

int main(void) {
#ifdef DEBUG
    printf("debug: starting\n");
#endif
    printf("running\n");
    return 0;
}

if, elif, else

#if จะประเมินนิพจน์จำนวนเต็มค่าคงที่ ใช้ร่วมกับ #elif และ #else เพื่อเลือกจากหลายกรณี

คำสั่งนี้เลือกโค้ดตามมาโครหมายเลขรุ่น

#include <stdio.h>
#define VERSION 2

int main(void) {
#if VERSION >= 2
    printf("new feature on\n");
#else
    printf("legacy mode\n");
#endif
    return 0;
}

ตัวดำเนินการ defined

ภายใน #if คุณสามารถตรวจสอบการกำหนดชื่อด้วย defined(NAME) และรวมการตรวจสอบด้วย && กับ || ได้

วิธีนี้ยืดหยุ่นกว่า #ifdef ซึ่งตรวจสอบได้เพียงชื่อเดียว

#if defined(LINUX) && !defined(EMBEDDED)
    /* desktop Linux code */
#endif

การกำหนดตอนคอมไพล์

คุณไม่จำเป็นต้องเขียนมาโครตายตัวในโค้ด แฟล็ก -D ใช้กำหนดมาโครผ่านบรรทัดคำสั่งได้

ระบบสร้างโปรแกรมใช้วิธีนี้เพื่อสลับคุณลักษณะโดยไม่ต้องแก้ไขซอร์ส -DDEBUG มีความหมายเหมือนกับการเขียน #define DEBUG ไว้ด้านบนของทุกไฟล์

gcc -DDEBUG -DVERSION=3 -o app app.c

การตรวจหาแพลตฟอร์ม

คอมไพเลอร์จะกำหนดมาโครที่อธิบายเป้าหมายไว้ล่วงหน้า คุณใช้มาโครเหล่านี้เพื่อเขียนโค้ดที่ทำงานได้หลายแพลตฟอร์ม

  • _WIN32 — Windows (32 หรือ 64 บิต)
  • __linux__ — Linux
  • __APPLE__ — macOS / iOS

ใช้เงื่อนไขแยกตามมาโครเหล่านี้เพื่อเรียกใช้ API ของแพลตฟอร์มที่ถูกต้อง

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif

ตัวป้องกันการรวมไฟล์ส่วนหัว

การใช้เงื่อนไขแบบคลาสสิกคือตัวป้องกันการรวมไฟล์ ซึ่งป้องกันไม่ให้ประมวลผลไฟล์ส่วนหัวซ้ำสองครั้ง

การรวมไฟล์ครั้งแรกจะกำหนดมาโครป้องกันไว้ ส่วนการรวมครั้งถัดไปจะข้ามเนื้อหา เพราะมีการกำหนดมาโครนั้นไว้แล้ว

#ifndef UTILS_H
#define UTILS_H

int add(int a, int b);

#endif /* UTILS_H */

การปิดใช้โค้ดด้วยคอมเมนต์

#if 0 ... #endif ปิดใช้บล็อกได้อย่างแน่นอน แม้บล็อกนั้นจะมีคอมเมนต์อยู่แล้ว

ต่างจาก /* */ ตรงที่สามารถซ้อนกันได้อย่างปลอดภัย จึงเป็นวิธีมาตรฐานสำหรับตัดโค้ดออกชั่วคราวระหว่างการแก้จุดบกพร่อง

#if 0
    legacy_function();   /* disabled for now */
    /* with internal comments too */
#endif

การตรวจสอบเอาต์พุตของตัวประมวลผลล่วงหน้า

หากต้องการดูสิ่งที่คอมไพเลอร์จะคอมไพล์อย่างแน่นอน ให้เรียกใช้เฉพาะตัวประมวลผลล่วงหน้าด้วย -E

คำสั่งนี้จะขยายการรวมไฟล์ มาโคร และเงื่อนไขทั้งหมด ซึ่งมีประโยชน์อย่างยิ่งเมื่อมาโครทำงานผิดพลาด

gcc -E app.c | less

การใช้สวิตช์คุณลักษณะในทางปฏิบัติ

รูปแบบที่ใช้กันทั่วไปคือการมีไฟล์ส่วนหัวสำหรับการตั้งค่าเพียงไฟล์เดียว เพื่อเปิดหรือปิดคุณลักษณะให้ทั้งโปรเจกต์

เปลี่ยน #define เพียงรายการเดียว แล้วทุกบล็อกที่มีเงื่อนไขป้องกันในทุกไฟล์จะตอบสนองตามนั้น วิธีนี้ช่วยแยกคุณลักษณะเสริมออกจากโค้ดหลักได้อย่างเป็นระเบียบ

#include <stdio.h>
#define FEATURE_LOGGING 1

int main(void) {
#if FEATURE_LOGGING
    printf("logging enabled\n");
#endif
    printf("app ready\n");
    return 0;
}

ตรวจสอบอย่างรวดเร็ว

คาดการณ์พฤติกรรมของการกำหนดค่าผ่านบรรทัดคำสั่ง

สรุปทบทวน

ขณะนี้คุณควบคุมการคอมไพล์แบบมีเงื่อนไขได้แล้ว:

  • #ifdef/#ifndef ตรวจสอบว่ามีการกำหนดมาโครหรือไม่
  • #if/#elif/#else ประเมินนิพจน์ค่าคงที่ร่วมกับ defined()
  • -DNAME กำหนดมาโครจากบรรทัดคำสั่งเพื่อสลับคุณลักษณะ
  • มาโครแพลตฟอร์มที่กำหนดไว้ล่วงหน้าช่วยให้เขียนโค้ดที่ทำงานได้หลายแพลตฟอร์ม และตัวป้องกันการรวมไฟล์จะป้องกันการรวมซ้ำ

ถัดไป: การจัดระเบียบโค้ดในหลายไฟล์

คำถามที่พบบ่อย

บทเรียน “การคอมไพล์แบบมีเงื่อนไข” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การคอมไพล์แบบมีเงื่อนไข” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การคอมไพล์แบบมีเงื่อนไข”

ifdef และมาโคร คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “การคอมไพล์แบบมีเงื่อนไข” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม

ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การคอมไพล์แบบมีเงื่อนไข
  2. โปรเจกต์หลายไฟล์
  3. Makefile
  4. ไลบรารีสแตติกและไลบรารีใช้ร่วมกัน
← กลับไปที่ C Academy