โปรเจกต์หลายไฟล์
ส่วนหัวและหน่วยแปล
โปรเจกต์หลายไฟล์ เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุผลที่ควรแยกไฟล์
โปรแกรมจริงไม่ได้อยู่ในไฟล์ .c เพียงไฟล์เดียว การแยกโค้ดเป็นหลายไฟล์ช่วยให้:
- จัดกลุ่มฟังก์ชันที่เกี่ยวข้องกันไว้ด้วยกัน
- ให้คอมไพเลอร์สร้างใหม่เฉพาะส่วนที่เปลี่ยนแปลง
- นำโค้ดกลับมาใช้ซ้ำในหลายโปรเจกต์
- ให้ทีมทำงานร่วมกันได้โดยไม่เกิดข้อขัดแย้งตลอดเวลา
การทำความเข้าใจว่าชิ้นส่วนต่าง ๆ เชื่อมโยงกันอย่างไรเป็นสิ่งสำคัญ
หน่วยแปล
ไฟล์ .c แต่ละไฟล์ หลังจากตัวประมวลผลล่วงหน้าขยาย #include แล้ว จะกลายเป็นหน่วยแปล
คอมไพเลอร์จะแปลงหน่วยแปลแต่ละหน่วยเป็นไฟล์อ็อบเจ็กต์ (.o) แยกจากกัน โดยในขั้นตอนนี้ยังไม่รู้จักไฟล์อื่น
การประกาศกับการนิยาม
การประกาศบอกคอมไพเลอร์ว่ามีฟังก์ชันอยู่และระบุลายเซ็นของฟังก์ชัน ส่วนการนิยามจะระบุเนื้อหาจริงของฟังก์ชัน
ไฟล์อื่นต้องการเพียงการประกาศเพื่อเรียกใช้ฟังก์ชัน ส่วนการนิยามจะอยู่ในที่เดียวเท่านั้น
int add(int a, int b); /* declaration: a promise */
int add(int a, int b) { /* definition: the body */
return a + b;
}ไฟล์ส่วนหัว
การประกาศจะอยู่ในไฟล์ส่วนหัว (.h) ไฟล์ใดก็ตามที่ต้องการใช้ฟังก์ชันจะรวมไฟล์ส่วนหัวนี้
ไฟล์ส่วนหัวคืออินเทอร์เฟซสาธารณะ ส่วนไฟล์ .c ที่ตรงกันคือการนำไปใช้งานภายใน
/* math_utils.h */
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
int mul(int a, int b);
#endifไฟล์การนำไปใช้งาน
ไฟล์ .c จะรวมไฟล์ส่วนหัวของตนเองและนิยามฟังก์ชันต่าง ๆ
การรวมไฟล์ส่วนหัวของตนเองช่วยให้คอมไพเลอร์ตรวจสอบได้ว่าการนิยามตรงกับการประกาศ
/* math_utils.c */
#include "math_utils.h"
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }การใช้โมดูล
ไฟล์อื่นจะรวมไฟล์ส่วนหัวและเรียกใช้ฟังก์ชัน โดยไม่จำเป็นต้องเห็นเนื้อหาภายในฟังก์ชัน
คอมไพเลอร์เชื่อถือการประกาศ ส่วนตัวเชื่อมโยงจะเชื่อมการเรียกใช้เข้ากับการนิยามจริงในภายหลัง
/* main.c */
#include <stdio.h>
#include "math_utils.h"
int main(void) {
printf("%d\n", add(2, 3));
return 0;
}การคอมไพล์และการเชื่อมโยง
มีสองขั้นตอน ขั้นแรกคอมไพล์แต่ละไฟล์เป็นไฟล์อ็อบเจ็กต์ด้วย -c จากนั้นเชื่อมโยงอ็อบเจ็กต์เหล่านั้นเข้าด้วยกันเป็นไฟล์ที่เรียกใช้ได้หนึ่งไฟล์
ตัวเชื่อมโยงจะค้นหาการนิยามใน math_utils.o เพื่อแก้การเรียกใช้ add แต่ละรายการ
gcc -c main.c # -> main.o
gcc -c math_utils.c # -> math_utils.o
gcc main.o math_utils.o -o appเครื่องหมายอัญประกาศกับวงเล็บแหลม
ไวยากรณ์การรวมไฟล์จะควบคุมเส้นทางการค้นหา:
#include "math_utils.h"จะค้นหาไดเรกทอรีโปรเจกต์ของคุณก่อน#include <stdio.h>จะค้นหาเฉพาะเส้นทางรวมไฟล์ของระบบ
ใช้เครื่องหมายอัญประกาศกับไฟล์ส่วนหัวของคุณเอง และใช้วงเล็บแหลมกับไลบรารีมาตรฐาน
คีย์เวิร์ด extern
หากต้องการใช้ตัวแปรโกลบอลร่วมกันระหว่างไฟล์ ให้นิยามตัวแปรนั้นครั้งเดียวในไฟล์ .c และประกาศด้วย extern ในไฟล์ส่วนหัว
extern หมายความว่า 'ตัวแปรนี้มีอยู่ที่อื่น' จึงช่วยหลีกเลี่ยงการนิยามซ้ำ
/* in config.h */
extern int g_verbose; /* declaration */
/* in config.c */
int g_verbose = 0; /* the single definition */คีย์เวิร์ด static
ในขอบเขตไฟล์ static จะทำให้ฟังก์ชันหรือตัวแปรเป็นส่วนตัวสำหรับหน่วยแปลของตนเอง
ฟังก์ชันช่วยแบบ static ไม่สามารถเชื่อมโยงจากไฟล์อื่นได้ จึงป้องกันชื่อชนกันและซ่อนรายละเอียดการนำไปใช้งาน นี่คือวิธีของ C ในการระบุว่าสิ่งใดเป็นส่วนภายใน
/* visible only inside this .c file */
static int helper(int x) {
return x * 2;
}กฎการนิยามเพียงครั้งเดียว
ฟังก์ชันที่ไม่ใช่แบบ static หรือโกลบอล อาจถูกนิยามได้เพียงครั้งเดียวเท่านั้นทั่วทั้งโปรแกรม คุณสามารถประกาศฟังก์ชันนั้นในหลายไฟล์ได้ แต่ต้องนิยามไว้ในไฟล์เดียว
การนิยาม add สองครั้งจะทำให้เกิดข้อผิดพลาดจากตัวเชื่อมโยง เช่น multiple definition of 'add' นี่จึงเป็นเหตุผลที่ไม่ควรใส่ตัวฟังก์ชันไว้ในไฟล์ส่วนหัว
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ลองพิจารณาว่าสิ่งใดควรอยู่ในไฟล์ส่วนหัว
ทบทวน
ตอนนี้คุณสามารถจัดโครงสร้างโครงการที่มีหลายไฟล์ได้แล้ว:
- แต่ละไฟล์
.cเป็นหน่วยแปลภาษาที่คอมไพล์เป็น.oได้อย่างอิสระ - ไฟล์ส่วนหัวเก็บการประกาศ ส่วนแต่ละการนิยามจะอยู่ในไฟล์
.cหนึ่งไฟล์ - ตัวเชื่อมโยงจะจัดการการเรียกใช้ข้ามไฟล์ออบเจ็กต์
externใช้แบ่งปันตัวแปรโกลบอล ส่วนstaticจะทำให้สัญลักษณ์เฉพาะไฟล์เป็นแบบส่วนตัว
ถัดไป: ทำให้กระบวนการสร้างเป็นอัตโนมัติด้วย Makefile
คำถามที่พบบ่อย
บทเรียน “โปรเจกต์หลายไฟล์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “โปรเจกต์หลายไฟล์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “โปรเจกต์หลายไฟล์”
ส่วนหัวและหน่วยแปล คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “โปรเจกต์หลายไฟล์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การคอมไพล์แบบมีเงื่อนไข
- โปรเจกต์หลายไฟล์
- Makefile
- ไลบรารีสแตติกและไลบรารีใช้ร่วมกัน