C ติดตั้งเครื่องมือและคอมไพล์โปรแกรมแรก



เราต้องมีคอมไพเลอร์ ตัวหลักมี 2 ตัวคือ GCC (GNU) และ Clang (LLVM) — โค้ดในซีรีส์นี้ใช้ได้กับทั้งคู่

ติดตั้ง

Linux (Ubuntu/Debian):

sudo apt update
sudo apt install build-essential gdb valgrind

build-essential มี gcc, make และไลบรารีมาตรฐาน

macOS:

xcode-select --install

ได้ clang (แต่พิมพ์ gcc ก็เรียก clang ให้)

Windows: ทางที่แนะนำที่สุดคือ WSL2 (wsl --install แล้วทำตามขั้น Ubuntu ด้านบน) เพราะบทหลัง ๆ ใช้ POSIX ทางเลือก: MSYS2 (pacman -S mingw-w64-ucrt-x86_64-gcc) หรือ MinGW-w64

เช็ค:

gcc --version
gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0

โปรแกรมแรก

สร้างไฟล์ hello.c

#include <stdio.h>

int main(void)
{
    printf("Hello, C!\n");
    return 0;
}
  • #include <stdio.h> — ดึงส่วนหัวของไลบรารี standard I/O เข้ามา (มี printf)
  • int main(void) — จุดเริ่มของโปรแกรม ทุกโปรแกรม C มี main หนึ่งตัว void แปลว่าไม่รับ argument
  • printf(...) — พิมพ์ข้อความ ต้องใส่ \n เองถ้าอยากขึ้นบรรทัดใหม่
  • return 0; — บอก OS ว่าโปรแกรมจบปกติ (ไม่ใช่ 0 = มีข้อผิดพลาด)

คอมไพล์และรัน

gcc hello.c -o hello
./hello
Hello, C!
  • gcc hello.c — ไฟล์ต้นทาง
  • -o hello — ตั้งชื่อไฟล์ผลลัพธ์ (ถ้าไม่ใส่ จะได้ชื่อ a.out)
  • ./hello — รัน (ต้องมี ./ บอกว่าอยู่โฟลเดอร์ปัจจุบัน)

คอมไพเลอร์ทำอะไรบ้าง — 4 ขั้นตอน

hello.c
   │  1. Preprocess — จัดการ #include, #define, #if  ->  hello.i (โค้ด C ล้วน ๆ ที่ขยายแล้ว)
   ▼
   │  2. Compile — แปลงเป็นภาษา assembly            ->  hello.s
   ▼
   │  3. Assemble — แปลง assembly เป็นภาษาเครื่อง     ->  hello.o (object file)
   ▼
   │  4. Link — รวม hello.o กับ libc (ที่มี printf)   ->  hello (executable)
   ▼
hello

ดูแต่ละขั้นได้:

gcc -E hello.c            # หยุดหลัง preprocess (พ่นออกจอ)
gcc -S hello.c            # ได้ hello.s
gcc -c hello.c            # ได้ hello.o
gcc hello.o -o hello      # link อย่างเดียว

ปกติเราสั่งบรรทัดเดียวให้ทำครบทั้ง 4 ขั้น แต่การรู้ว่ามีขั้นอะไรบ้างช่วยเข้าใจ error: error ตอน compile ต่างจาก error ตอน link (เช่น undefined reference to 'foo' = link หาฟังก์ชันไม่เจอ)

flag ประจำตัว — ใช้ทุกครั้ง

gcc -std=c17 -Wall -Wextra -g hello.c -o hello
flagทำอะไร
-std=c17ตรึงมาตรฐานเป็น C ปี 2017 (หรือ c11) — ค่าเริ่มต้นของ gcc ต่างกันตามรุ่น (เก่า = gnu11/gnu17, gcc 15 = gnu23) เราตรึงไว้เพื่อให้ทุกบทเรียนสม่ำเสมอ
-Wallเปิดคำเตือนที่มีประโยชน์ (ไม่ใช่ “ทั้งหมด” อย่างที่ชื่อบอก)
-Wextraเปิดคำเตือนเพิ่มอีกชุด
-gใส่ข้อมูล debug (ให้ gdb ใช้ได้)
-O2เปิด optimization (ใช้ตอน build จริง ไม่ใช่ตอน debug)

เปิด -Wall -Wextra แล้วแก้ทุก warning — warning ของ C มักชี้บั๊กจริง เช่น “ใช้ตัวแปรก่อน initialize”, “return type ไม่ตรง”

ตัวช่วยจับบั๊กหน่วยความจำ (บทที่ 15, 29):

gcc -std=c17 -Wall -Wextra -g -fsanitize=address,undefined hello.c -o hello

ลองทำให้ warning โผล่

#include <stdio.h>

int main(void)
{
    int x;
    printf("%d\n", x);      // ใช้ x ที่ยังไม่ได้กำหนดค่า
    return 0;
}
gcc -O1 -Wall -Wextra hello.c -o hello
hello.c:6:5: warning: 'x' is used uninitialized [-Wuninitialized]

การตรวจ uninitialized ของ GCC ทำงานตอนวิเคราะห์ dataflow ของ optimizer — ต้องเปิด optimization อย่างน้อย -O1 ถ้าคอมไพล์ -O0 (ค่าเริ่มต้น) มักไม่เตือน และผลอาจต่างกันตามรุ่น compiler ด้วย ถ้าไม่ใส่ -Wall เลยก็เงียบสนิท แล้วโปรแกรมพิมพ์ค่าขยะออกมา — เครื่องมือที่จับได้แน่นอนกว่าคือ -fsanitize=memory (Clang) หรือ valgrind

รวบเป็น alias หรือ Makefile

พิมพ์ flag ทุกครั้งเหนื่อย — ตั้ง alias ชั่วคราว:

alias cc17='gcc -std=c17 -Wall -Wextra -g'
cc17 hello.c -o hello

บทที่ 27 เราจะใช้ Makefile จัดการเรื่องนี้อย่างเป็นระบบ

เรื่องที่คนมักพลาด

  • ลืม ./ ตอนรัน — พิมพ์ hello เฉย ๆ shell หาใน PATH ไม่เจอ ต้อง ./hello
  • ไม่ใส่ -Wall -Wextra — พลาด warning ที่ชี้บั๊กจริง เปิดไว้เสมอ
  • undefined reference to 'sqrt' ตอน link — ฟังก์ชันคณิตศาสตร์อยู่ใน libm ต้องเติม -lm ท้ายคำสั่ง
  • แก้โค้ดแล้วรัน ./hello เลย โดยลืมคอมไพล์ใหม่ — ยังได้ผลลัพธ์เก่า ต้อง gcc ... ก่อนทุกครั้ง
  • gcc บน Windows ไม่มี — ติดตั้ง WSL หรือ MSYS2 อย่าใช้ Dev-C++ / Turbo C ที่เก่ามาก
  • วางลำดับ flag ผิด — library (-lm, -lfoo) ต้องมา หลัง ไฟล์ที่ใช้มัน

สรุป

  • ติดตั้ง GCC/Clang: build-essential (Linux), xcode-select --install (macOS), WSL (Windows)
  • คอมไพล์: gcc file.c -o prog แล้วรัน ./prog
  • 4 ขั้น: preprocess → compile → assemble → link — error แต่ละขั้นต่างกัน
  • ใช้ -std=c17 -Wall -Wextra -g ทุกครั้ง และแก้ทุก warning
  • -fsanitize=address,undefined เพื่อจับบั๊กหน่วยความจำ

บทถัดไปว่าด้วยโครงสร้างโปรแกรม C ให้ละเอียด — #include, main, return, และ printf กับ format specifier