Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 1.114 phút đọc

Tổng quan về C

Sau bài này bạn sẽ làm được

  • Kể được các mốc chính trong lịch sử C và các phiên bản chuẩn
  • Chỉ ra được ít nhất sáu lĩnh vực đang dùng C trong thực tế
  • So sánh được C với C++, Java và Rust trên các tiêu chí quan trọng
  • Giải thích được vị trí của C trong sơ đồ phân tầng của một hệ thống

C là ngôn ngữ lập trình ra đời năm 1972 và tới nay vẫn nằm dưới đáy của gần như mọi hệ thống phần mềm bạn đang dùng. Bài này trả lời ba câu hỏi: C đến từ đâu, nó đang chạy ở những nơi nào, và vì sao học C lại đáng công dù có nhiều ngôn ngữ mới hơn.

#Lịch sử C

C không được thiết kế để dạy học. Nó ra đời vì một nhóm kỹ sư ở Bell Labs cần một ngôn ngữ đủ gần phần cứng để viết hệ điều hành, nhưng đủ cao để không phải viết lại từ đầu mỗi khi đổi máy.

NămSự kiện
1969 tới 1973Dennis Ritchie tạo ra C tại Bell Labs, phát triển từ ngôn ngữ B của Ken Thompson
1973Nhân UNIX được viết lại bằng C. Lần đầu tiên một hệ điều hành được viết bằng ngôn ngữ bậc cao
1978Sách K&R ra mắt, đặt ra chuẩn mực không chính thức đầu tiên
1989 và 1990ANSI C rồi ISO C90, chuẩn hóa chính thức
1999C99: //, bool, long long, VLA, inline, snprintf
2011C11: _Generic, <threads.h>, <stdatomic.h>, _Static_assert
2018C17 và C18, chỉ sửa lỗi biên tập, không có tính năng mới
2024C23: nullptr, constexpr, typeof, #embed, thuộc tính kiểu [[nodiscard]]
Các mốc chính. Từ C99 trở đi, mỗi phiên bản chuẩn được đặt tên theo năm ban hành.

#Dennis Ritchie

Dennis Ritchie (1941 tới 2011) là cha đẻ của C và đồng tác giả UNIX. Ảnh hưởng của ông rộng tới mức khó hình dung: C++, Objective-C, C#, Java, JavaScript, PHP, Go và Rust đều mượn cú pháp từ C. Nếu bạn từng viết một vòng lặp for ở bất kỳ ngôn ngữ nào trong số đó, bạn đã dùng thiết kế của Ritchie.

Ông tự nhận xét về ngôn ngữ của mình một cách khá thẳng thắn: C kỳ quặc, có khiếm khuyết, và thành công vang dội. Cả ba vế đều đúng, và bài học này sẽ cho bạn thấy tại sao.

#C được dùng ở đâu

Câu trả lời ngắn: ở tầng dưới cùng của gần như mọi thứ. Đây không phải nói quá, mà là hệ quả trực tiếp của việc C có thể chạy mà không cần bất kỳ hạ tầng nào bên dưới nó.

Lĩnh vựcVí dụ cụ thể
Hệ điều hànhNhân Linux (khoảng 28 triệu dòng C), nhân Windows, macOS và XNU, FreeBSD
Nhúng và IoTFirmware STM32, ESP32, Arduino, hệ thống trên ô tô, máy giặt, vệ tinh
Cơ sở dữ liệuSQLite, PostgreSQL, MySQL, Redis
MạngNginx, curl, OpenSSL, Wireshark
Ngôn ngữ khácCPython, PHP, Ruby MRI, Lua, Perl. Trình thông dịch của chúng đều viết bằng C
Đồ họa và đa phương tiệnFFmpeg, OpenGL, Git
Khoa học và tính toán hiệu năng caoBLAS, LAPACK, lõi của NumPy

#Vị trí của C trong hệ thống

Một hệ thống phần mềm có nhiều tầng. Càng xuống dưới càng gần phần cứng, càng ít thứ có sẵn để dựa vào. C chiếm trọn ba tầng ở giữa.

Ứng dụng ở trên có thể viết bằng bất kỳ ngôn ngữ nào, nhưng mọi thứ đỡ nó ở dưới đều là C.

Điều đáng chú ý là chiều mũi tên phụ thuộc. Python gọi được thư viện C, nhưng C không cần Python. Java chạy trên máy ảo, mà máy ảo đó viết bằng C và C++. Đây chính là lý do C chưa bị thay thế: muốn thay nó, bạn phải thay cả nền móng.

Ngôn ngữ hệ thống
Ngôn ngữ có thể chạy mà không cần môi trường thực thi (runtime) nào bên dưới, tự quản lý bộ nhớ, và truy cập được trực tiếp địa chỉ phần cứng. C, C++, Rust và Zig thuộc nhóm này. Python, Java, JavaScript thì không.

#So với C++, Java, Rust

Tiêu chíCC++JavaRust
Năm ra đời1972198519952010
Quản lý bộ nhớThủ côngThủ công và RAIITự động, có bộ dọn rácOwnership
An toàn bộ nhớKhôngMột phầnCó, kiểm tra lúc biên dịch
Kích thước runtimeGần bằng 0NhỏLớnNhỏ
Tốc độRất nhanhRất nhanhNhanh vừaRất nhanh
Thời gian biên dịchRất nhanhChậmNhanhChậm
Dùng cho hệ nhúngChuẩn mựcĐượcHiếmĐang lên
Độ khóCú pháp dễ, dùng đúng thì khóRất khóDễKhó vì borrow checker
Bảng này để định vị, không phải để xếp hạng. Mỗi ngôn ngữ tối ưu cho một bài toán khác nhau.

Điểm quan trọng nhất trong bảng trên nằm ở dòng an toàn bộ nhớ. C không bảo vệ bạn. Nếu bạn ghi ra ngoài mảng, nó cứ ghi. Nếu bạn dùng vùng nhớ đã giải phóng, nó cứ dùng. Học C là học chịu trách nhiệm hoàn toàn với từng byte, và đó cũng chính là thứ khiến bạn hiểu máy tính thật sự hoạt động ra sao.

#Ưu điểm và nhược điểm

Vì sao nên học

  • Nhanh. Mã sinh ra gần như ngang assembly viết tay, mà không phải viết assembly.
  • Nhỏ. Chuẩn C89 chỉ có 32 từ khóa. Bạn có thể thuộc toàn bộ ngôn ngữ, điều không thể làm với C++.
  • Khả chuyển. Gần như mọi kiến trúc từng tồn tại đều có trình biên dịch C.
  • Kiểm soát tuyệt đối. Bạn quyết định từng byte nằm ở đâu và sống bao lâu.
  • Giao diện nhị phân ổn định. Mọi ngôn ngữ khác đều gọi được thư viện C. Đây là lý do C là ngôn ngữ chung của cả ngành.

Cái giá phải trả

  • Không an toàn bộ nhớ. Tràn bộ đệm, con trỏ treo, dùng vùng nhớ đã giải phóng. Đây là nguồn gốc phần lớn lỗ hổng bảo mật nghiêm trọng trong 30 năm qua.
  • Thư viện chuẩn rất nghèo. Không có kiểu chuỗi thực thụ, không có mảng động, không có bảng băm. Bạn tự viết hoặc đi tìm thư viện.
  • Không có trình quản lý gói. Không có npm hay pip cho C.
  • Hành vi không xác định. Sai một chút, chương trình sai theo cách rất khó đoán. Cả Phần 13 dành riêng cho chủ đề này.
  • Xử lý lỗi thủ công. Không có ngoại lệ, nên bạn sẽ viết if (!p) return -1; rất nhiều lần.

Tự làm thử

  1. Mở terminal và chạy ls /usr/include/*.h | wc -l để đếm số header của thư viện chuẩn trên máy bạn.
  2. Tra cứu xem nhân Linux hiện có bao nhiêu dòng mã và bao nhiêu phần trăm là C.
  3. Viết khoảng 200 từ trả lời: Rust được gọi là C an toàn, vậy nó giải quyết nhược điểm nào trong danh sách ở trên, và đánh đổi lại điều gì?

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • C ra đời năm 1972 tại Bell Labs, do Dennis Ritchie tạo ra để viết hệ điều hành UNIX.
  • Các chuẩn quan trọng: C89, C99, C11, C17 và C23. Khóa học này dùng -std=c17.
  • C chiếm ba tầng giữa của mọi hệ thống: thư viện hệ thống, nhân hệ điều hành và firmware.
  • Ưu điểm lớn nhất là tốc độ và kiểm soát tuyệt đối. Nhược điểm lớn nhất là không an toàn bộ nhớ.
  • Cú pháp C dễ học, nhưng dùng C đúng thì khó. Đó là trọng tâm của khóa học.