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

Ba nhóm cờ: cảnh báo, chuẩn, gỡ lỗi

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

  • Chọn bộ cờ cảnh báo phù hợp cho dự án
  • Chọn chuẩn ngôn ngữ và hiểu gnu17 khác c17 thế nào
  • Dùng -g3 và -fno-omit-frame-pointer đúng lúc
  • Biết cờ nào nên là -Werror

Ba nhóm cờ bạn đặt cho mỗi dự án: cảnh báo để bắt lỗi sớm, chuẩn ngôn ngữ để mã có nghĩa xác định, và cờ gỡ lỗi để công cụ đọc được chương trình. Bài này gom chúng thành một dòng lệnh bạn chép đi chép lại.

#Nhóm cảnh báo

# Muc toi thieu, dat cho MOI du an ngay tu file dau tien
-Wall -Wextra -Wpedantic

# Muc nghiem tuc, them cac co bat loi that ma -Wall bo qua
-Wshadow              # bien che khuat bien ngoai
-Wconversion          # ep kieu ngam co the mat du lieu
-Wsign-conversion     # ep signed <-> unsigned
-Wcast-qual           # ep bo const hoac volatile
-Wstrict-prototypes   # ham khai bao khong co nguyen mau
-Wmissing-prototypes  # ham cong khai thieu nguyen mau trong header
-Wformat=2            # kiem tra chuoi dinh dang nghiem ngat
-Wnull-dereference    # giai tham chieu con tro co the NULL
-Wdouble-promotion    # float bi thang len double ngoai y muon
-Wvla                 # canh bao mang do dai bien
-Wswitch-enum         # switch thieu case cua enum
terminal
# -Wvla bao mang do dai bien, thu la
gcc -std=c11 -Wall -Wextra -Wvla std.c -o /dev/null
std.c: In function 'main':
std.c:4:5: warning: ISO C90 forbids variable length array 'a' [-Wvla]
     int a[n];

#Chuẩn ngôn ngữ

CờChuẩnGhi chú
-std=c89C89 / C90 / ANSI CRất cũ, chỉ khi buộc phải
-std=c99C99Có // comment, khai báo giữa hàm, VLA
-std=c11C11_Static_assert, _Generic, threads, atomics
-std=c17C17Như C11, chủ yếu sửa lỗi chuẩn; mặc định nên dùng
-std=c2xC23Mới nhất, hỗ trợ còn tuỳ trình biên dịch
-std=gnu17C17 + mở rộng GNUMặc định của GCC nếu không đặt gì

#gnu17 khác c17

Phần mở rộng GNU
Các tính năng GCC thêm vào ngoài chuẩn C: typeof, biểu thức câu lệnh ({ ... }), mảng độ dài không, hằng nhị phân 0b1010, và nhiều thứ khác. gnu17 bật chúng; c17 tắt.
# Mac dinh cua GCC neu ban khong dat -std
gcc file.c                  # = -std=gnu17

# Chuan thuan, khong mo rong
gcc -std=c17 file.c

#Cờ gỡ lỗi

-g                    # thong tin go loi co ban
-g3                   # + thong tin MACRO (go loi duoc ca #define)
-ggdb                 # dinh dang toi uu cho GDB
-fno-omit-frame-pointer   # giu con tro khung -> backtrace chinh xac
terminal
# -g3 them thong tin macro, nen file lon hon -g
gcc -std=c11 -g std.c -o std_g.exe && stat -c%s std_g.exe
54716
gcc -std=c11 -g3 std.c -o std_g3.exe && stat -c%s std_g3.exe
80890

#Cờ nào nên là lỗi

Dòng lệnh gom lại, bản debug
gcc -std=c17 \
    -Wall -Wextra -Wpedantic -Wshadow -Wconversion \
    -Wstrict-prototypes -Wmissing-prototypes -Wformat=2 \
    -Werror=implicit-function-declaration -Werror=return-type \
    -g3 -O0 \
    src/*.c -o build/app_debug

Tự làm thử

  1. Dán bộ cờ cảnh báo đầy đủ vào một dự án của bạn và đếm cảnh báo mới.
  2. Viết một mảng độ dài biến và xác nhận -Wvla bắt được.
  3. Dịch cùng tệp với -std=c17 và -std=gnu17, tìm một mở rộng GNU chỉ dịch được ở bản sau.
  4. So kích thước binary giữa -g và -g3 trên mã của bạn.
  5. Tách thông tin gỡ lỗi ra tệp riêng bằng objcopy trên Linux.
  6. Thêm bốn cờ -Werror= và kiểm tra dự án của bạn vẫn dịch được.

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

  • Bộ cảnh báo tối thiểu là -Wall -Wextra -Wpedantic; các cờ giá trị nhất nằm ngoài chúng.
  • Luôn đặt -std rõ ràng; mặc định nên là -std=c17.
  • c17 tắt mở rộng GNU nên phát hiện phụ thuộc không di động ngay tại máy bạn; gnu17 là mặc định của GCC.
  • -g không làm chậm mã và nên bật cả ở bản phát hành; -g3 thêm thông tin macro.
  • Bốn cảnh báo về hàm chưa khai báo, thiếu return, và trộn con trỏ nên là -Werror ở mọi nơi.