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

Đặt tên

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

  • Áp dụng một quy ước đặt tên nhất quán
  • Đặt tiền tố cho mọi ký hiệu công khai của thư viện
  • Tránh sáu kiểu tên gây hiểu nhầm
  • Đặt tên hàm theo cặp đối xứng

Mã của bạn được đọc nhiều hơn được viết, và thứ được đọc nhiều nhất trong mã là tên. Một cái tên tốt tiết kiệm một câu bình luận; một cái tên xấu tạo ra một lỗi.

#Chọn một quy ước

LoạiKiểu C chuẩnKiểu Linux kernelKiểu này dùng trong sách
Hàmdo_the_thingdo_the_thingtinh_dien_tich
Biến cục bộcountcntso_luong
Tham sốn, bufn, bufn, bo_dem
Kiểu structstruct foo_barstruct foo_barSinhVien
typedeffoo_bar_tÍt dùng typedefSinhVien
Hằng, macroMAX_SIZEMAX_SIZECO_TOI_DA
Biến toàn cụcg_countcountg_so_luong
Trường structnamenameten
Tệpfoo_bar.cfoo-bar.cdanh_sach.c

#Tiền tố cho ký hiệu công khai

Không gian tên phẳng
C không có namespace. Mọi ký hiệu không phải static nằm chung một không gian tên duy nhất cho toàn bộ chương trình, kể cả các thư viện được liên kết vào. Tiền tố là cách duy nhất để tránh va chạm.
Không nên
/* hinh.h, thu vien hinh hoc cua ban */ double dien_tich(double r); double chu_vi(double r); void ve(Hinh *h); int khoi_tao(void); /* Bon ten pho bien nhat the gioi. Ban vua chiem ca bon trong khong gian ten TOAN CUC cua moi chuong trinh dung thu vien nay. */
Nên
/* hinh.h */ double hinh_dien_tich(double r); double hinh_chu_vi(double r); void hinh_ve(Hinh *h); int hinh_khoi_tao(void); /* Cac thu vien that deu lam vay: SQLite sqlite3_open, sqlite3_exec zlib deflate, inflate, gzopen (tien to gz cho mot phan) libcurl curl_easy_init, curl_easy_setopt OpenSSL SSL_new, EVP_EncryptInit_ex, X509_verify */

#Va chạm tên

Va chạm với thư viện chuẩn
#include <stdio.h>

typedef struct { int *pt; int co; } DsSo;

/* Xoa mot phan tu khoi danh sach */
int remove(DsSo *d, int vi_tri) {
    if (vi_tri < 0 || vi_tri >= d->co) return -1;
    for (int i = vi_tri; i + 1 < d->co; ++i) d->pt[i] = d->pt[i + 1];
    d->co--;
    return 0;
}
terminal
gcc -std=c11 -Wall -Wextra vacham2.c -o vacham2.exe
vacham2.c:7:5: error: conflicting types for 'remove'
 int remove(DsSo *d, int vi_tri) {
     ^~~~~~
In file included from vacham2.c:2:
.../include/stdio.h:676:15: note: previous declaration of 'remove' was here
   int __cdecl remove(const char *_Filename);
               ^~~~~~

#Sáu kiểu tên gây hiểu nhầm

Một: tên nói dối
int dem_ky_tu(const char *s) {
    int n = 0;
    while (*s) { if (*s != ' ') ++n; ++s; }   /* KHONG dem dau cach */
    return n;
}

/* Ten noi "dem ky tu", ma khong dem dau cach.
   Nguoi goi tin ten, khong doc than ham, va sinh ra mot loi.

   Ten dung: dem_ky_tu_khong_trang, hoac doi ham cho khop ten. */
Hai: tên khác nhau cho cùng một thứ
typedef struct { ... } NguoiDung;

NguoiDung *lay_nguoi_dung(int id);
NguoiDung *tim_user(const char *ten);
NguoiDung *doc_tai_khoan(int id);
NguoiDung *nap_thanh_vien(int id);

/* Bon tu cho MOT khai niem, va ba dong tu cho MOT hanh dong.
   Nguoi doc phai tu hoi: "doc" va "nap" khac nhau cho nao?

   Chon MOT tu cho MOI khai niem va viet vao tai lieu:
     nguoi_dung   khong dung user, tai khoan, thanh vien
     lay          khong dung tim, doc, nap  */

NguoiDung *nguoi_dung_lay_theo_id(int id);
NguoiDung *nguoi_dung_lay_theo_ten(const char *ten);
Ba: tên chỉ khác nhau một chữ
int  xu_ly_don_hang(Don *d);
int  xu_ly_don_hang_2(Don *d);
int  xu_ly_don_hang_moi(Don *d);
int  xu_ly_don_hang_cu(Don *d);

/* Ban se goi nham. Khong phai co the, ma la chac chan.
   Nhat la trong danh sach tu dong hoan thanh cua trinh soan thao.

   Neu ban thay minh dat ten kieu nay, do la dau hieu thiet ke sai:
   bon ham do co gi khac nhau ma khong noi ra duoc bang tu? */

int don_hang_xac_nhan(Don *d);
int don_hang_huy(Don *d);
int don_hang_giao(Don *d);
Bốn: mã hoá kiểu vào tên
int    iSoLuong;            /* ky phap Hungary */
char  *szTen;
double dGiaTri;
LPCSTR lpszDuongDan;

/* Vi sao no da chet:
   - Trinh bien dich da biet kieu. Ban khong can nhac lai.
   - Khi ban doi int thanh long, ban phai doi TEN o moi cho.
     Va neu ban luoi thi ten noi doi.
   - Trinh soan thao hien kieu khi ban tro chuot vao.

   Nhung mot phan cua Hungary VAN co ich: ma hoa Y NGHIA,
   khong phai kieu. Do la "Hungary ung dung": */

int rong_px;        /* pixel */
int rong_em;        /* em */
int cho_ms;         /* mili giay */
int cho_s;          /* giay */

/* Bay gio  cho_ms = cho_s  la mot loi ban NHIN THAY duoc,
   trong khi  int a = int b  thi khong. */
Năm: phủ định trong tên
if (!khong_hop_le(x)) { ... }           /* hai lan phu dinh */
if (!chua_khoi_tao) { ... }
if (!bo_qua_kiem_tra) { ... }

/* Nao khong hop le nghia la hop le? Nao chua khoi tao nghia la
   da khoi tao? Moi lan doc la mot lan phai dao nguoc trong dau.

   Dat ten o dang KHANG DINH: */
if (hop_le(x)) { ... }
if (da_khoi_tao) { ... }
if (can_kiem_tra) { ... }
Sáu: tên chung chung
void xu_ly(void *du_lieu);
int  kiem_tra(int x);
Data *lay_du_lieu(void);
void thuc_hien(void);
int  quan_ly_trang_thai(int co);

/* "Xu ly" cai gi? "Kiem tra" dieu gi va tra ve gi?

   Neu ban khong dat duoc mot cai ten cu the cho ham, thuong la
   vi ham do lam QUA NHIEU viec. Ten chung chung la mot mui
   thiet ke, khong chi la mot van de tham my. */

void don_hang_tinh_thue(DonHang *d);
int  email_dung_dinh_dang(const char *s);
CauHinh *cau_hinh_doc_tu_tep(const char *duong_dan);

#Đặt tên theo cặp

Dùng cho
taohuyCấp phát và giải phóng một đối tượng
modongTài nguyên hệ thống: tệp, socket, kết nối
khoi_taodon_depCấu trúc do người gọi cấp bộ nhớ
themxoaBộ chứa
daylayNgăn xếp, hàng đợi
khoamo_khoaMutex
bat_dauket_thucMột giai đoạn có thời gian
dang_kyhuy_dang_kyBộ xử lý sự kiện, hàm gọi lại
napluuBền vững hoá
ma_hoagiai_maChuyển đổi hai chiều
Header khó đọc
/* ds.h */ Ds *create(void); void destroy(Ds *d); int add(Ds *d, int x); int get(Ds *d, int i); int size(Ds *d); void clear(Ds *d); int find(Ds *d, int x);
Header tự giải thích
/* ds.h */ Ds *ds_tao(void); void ds_huy(Ds *d); int ds_them(Ds *d, int x); int ds_lay(const Ds *d, size_t i, int *ra); size_t ds_so_luong(const Ds *d); void ds_xoa_het(Ds *d); long ds_tim(const Ds *d, int x); /* -1 neu khong thay */ /* Ba cai duoc them ngoai tien to: - const cho ham chi doc: doc header la biet ham nao sua - size_t cho chi so va so luong, khong dung int - ds_lay tra ve ma loi va dua gia tri qua *ra, vi moi gia tri int deu hop le nen khong co gia tri "loi" */

Tự làm thử

  1. Viết ra quy ước đặt tên của dự án bạn đang làm, một trang, và dán vào CONTRIBUTING.md.
  2. Tìm trong mã của bạn một hàm không phải static mà lẽ ra phải là, và sửa.
  3. Tái hiện lỗi multiple definition bằng hai tệp và giải thích vì sao bước biên dịch không báo gì.
  4. Lấy một header của bạn và thêm tiền tố cho mọi ký hiệu công khai.
  5. Tìm một tên phủ định trong mã của bạn và viết lại ở dạng khẳng định.
  6. Liệt kê mọi cặp tạo và huỷ trong dự án của bạn, và kiểm tra chúng có đối xứng không.

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

  • Nhất quán quan trọng hơn đẹp: chọn một quy ước và giữ nó.
  • C có không gian tên phẳng, nên mọi ký hiệu công khai cần tiền tố, và mọi thứ không phải giao diện phải là static.
  • Va chạm tên với thư viện chuẩn có thể là lỗi biên dịch, lỗi liên kết, hoặc im lặng; tên bắt đầu bằng gạch dưới là dành riêng.
  • Sáu kiểu tên xấu: nói dối, không nhất quán, khác một chữ, mã hoá kiểu, phủ định, và chung chung.
  • Đặt tên theo cặp đối xứng để mắt quét được và thấy ngay chỗ thiếu.