C Ngôn Ngữ: Cú Pháp Cơ Bản

1. Biên dịch và Liên kết Chương trình

  • Xử lý tiền xử lý: mở rộng tệp tiêu đề, thay thế văn bản, loại bỏ chú thích, biên dịch điều kiện.
  • Tập hợp: phân tích cú pháp + tổng hợp ký hiệu.
  • Biên dịch: chuyển đổi mã nguồn thành lệnh nhị phân.
  • Liên kết: kết hợp các tệp: giải quyết ký hiệu, điều chỉnh địa chỉ, tạo bảng ký hiệu.

2. Định nghĩa Macro bằng #define

  • Macro: thay thế văn bản.
  • Nhược điểm: a) Không kiểm tra kiểu, khó gỡ lỗi. b) Có thể bị ảnh hưởng bởi ưu tiên phép tính. c) Dễ dẫn đến lặp mã, làm tăng kích thước mã.
  • Lợi ích: a) Không có chi phí khung ngăn xếp hàm (nhanh hơn).

Định nghĩa hằng số

#define PI 3.14159
#define MAX_VALUE 100

Định nghĩa hàm

#define SQUARE(x) ((x) * (x))

Thay thế đoạn mã

#define DEBUG_PRINT(x) printf("DEBUG: " #x " = %d\n", x)

3. Biên dịch Điều kiện

  • Làm việc của bộ xử lý tiền xử lý, cho phép lựa chọn bao gồm hoặc loại trừ một phần mã dựa trên điều kiện tại thời điểm biên dịch.
  • Các loại: #if, #ifdef, #ifndef, #elif, và #else.

#if

#if BIỂU_THỨC_ĐIỀU_KIỆN
    // Khối mã
#endif

#ifdef

#ifdef TÊN_MACRO
    // Khối mã
#endif

#ifndef

#ifndef TÊN_MACRO
    // Khối mã
#endif

#elif

#if BIỂU_THỨC_ĐIỀU_KIỆN_1
    // Khối mã 1
#elif BIỂU_THỨC_ĐIỀU_KIỆN_2
    // Khối mã 2
#else
    // Khối mã 3
#endif

#else

#if BIỂU_THỨC_ĐIỀU_KIỆN
    // Khối mã 1
#else
    // Khối mã 2
#endif

Ngăn chặn việc bao gồm nhiều lần cùng một tệp tiêu đề

Sử dụng chỉ thị tiền xử lý #pragma once

#ifndef TEN_TEP_TIEU_DE_H
#define TEN_TEP_TIEU_DE_H

// Nội dung của tệp tiêu đề

#endif

4. Sự khác biệt giữa dấu ngoặc kép "" và dấu ngoặc nhọn <> khi bao gồm tệp tiêu đề

  • Dấu ngoặc kép: tìm kiếm trước trong thư mục chứa tệp nguồn, sau đó tìm trong đường dẫn chuẩn nếu không tìm thấy.
  • Dấu ngoặc nhọn: tìm trực tiếp trong đường dẫn chuẩn.

5. Mã Nguyên, Mã Đảo và Mã Bù

  • Mã nguyên, mã đảo và mã bù của số dương giống nhau.
  • Mã đảo của số âm được lấy bằng cách đảo ngược mã nguyên, mã bù được lấy bằng cách cộng 1 vào mã đảo, cộng 1 vào mã bù sẽ lại được mã nguyên.
  • Số nguyên trong C được lưu dưới dạng mã bù trong bộ nhớ.
Giá trị Mã Nguyên Mã Đảo Mã Bù
+0 00000000 00000000 00000000
-0 10000000 11111111 00000000
+3 00000011 00000011 00000011
-3 10000011 11111100 11111101

6. Thuật toán Byte Order (Ký tự Kết thúc)

  • Kiểu byte order: cách dữ liệu được lưu trữ trong bộ nhớ.
  • Kiểu Big-endian: byte thấp được lưu ở địa chỉ cao.
  • Kiểu Little-endian: byte thấp được lưu ở địa chỉ thấp.

Ví dụ: 0x12345678 --Big-endian: 0x12 0x34 0x56 0x78 -- Little-endian: 0x78 0x56 0x34 0x12

Phương pháp xác định Big-endian hay Little-endian:

Sử dụng con trỏ

int kiemtra_hethong() 
{
    int gia_tri = 1;
    return *(char*)(&gia_tri); // 1 : Little-endian  0 : Big-endian
}

Sử dụng union

int kiemtra_hethong() 
{
    union kiemtra
    {
        int gia_tri;
        char mang[4];
    };
 
    union kiemtra du_lieu;
    du_lieu.gia_tri = 1;
    return du_lieu.mang[0]; 
}

7. Lưu trữ Số thực trong Bộ nhớ

|  Bit Ký hiệu  |     Bit Chỉ số    |        Bit Phân số        |
|---------------|-------------------|---------------------------|
|       s       |         e         |             f             |
  • Bit Ký hiệu (s): 1 bit, 0 cho số dương, 1 cho số âm.
  • Bit Chỉ số (e): 8 bit, biểu diễn phần chỉ số của số thực.
  • Bit Phân số (f): 23 bit, biểu diễn phần phân số của số thực.

8. Kiểu Dữ liệu struct

struct Nguoi {
    char gioi_tinh;
    char ten[15];
    int tuoi;
};

Đối齐 bộ nhớ

  • Lý do về nền tảng: không phải tất cả các nền tảng phần cứng đều có thể truy cập dữ liệu ở bất kỳ địa chỉ nào.
  • Lý do về hiệu suất: để đọc dữ liệu một cách hiệu quả nhất.

Các quy tắc đối齐 bộ nhớ trong struct

  • Thành viên đầu tiên bắt đầu từ địa chỉ 0.
  • Các thành viên khác được căn chỉnh đến bội số của kích thước tối đa.
  • Kích thước tổng cộng của struct là bội số của kích thước tối đa.

9. Kiểu Dữ liệu union

union ten_union {
    kieu_thanh_vien1 thanh_vien1;
    kieu_thanh_vien2 thanh_vien2;
    // có thể có thêm thành viên
};

10. Kiểu Dữ liệu enum

enum ThuTrongTuan {
    ThuHai,       //0
    ThuBa,        //1
    ThuTu,        //2
    ThuNam,       //3
    ThuSau,       //4
    ThuBay,       //5
    ChuNhat       //6
};

11. Con trỏ

  • Con trỏ là biến lưu trữ địa chỉ, thông qua con trỏ có thể truy cập trực tiếp dữ liệu tại vị trí đó.
  • Kiểu của con trỏ xác định số byte mà phép giải tham chiếu có thể truy cập.

Các loại con trỏ

char *chi_so = "xin chào thế giới";
int (*chi_so_mang)[10];
int* mang_chi_so[10];
void (*chi_so_ham)();
int (*mang_chi_so_ham[10])();
int (*(*chi_so_mang_chi_so_ham)[10])();

Mảng và Con trỏ

Truyền tham số

Mảng một chiều

void kiemtra(int mang[]) {}
void kiemtra(int mang[10]) {}
void kiemtra(int *mang) {}
void kiemtra2(int *mang[20]) {}
void kiemtra2(int **mang) {}
 
int main()
{
    int mang[10] = {0};
    int *mang2[20] = {0};
    kiemtra(mang);
    kiemtra2(mang2);
}

Mảng hai chiều

void kiemtra(int mang[3][5]) {}
void kiemtra(int mang[][5]) {}
void kiemtra(int (*mang)[5]) {}
 
int main()
{
    int mang[3][5] = {0};
    kiemtra(mang);
}

&tên mảng và tên mảng

  • tên mảng: địa chỉ của phần tử đầu tiên.
  • &tên mảng: địa chỉ của toàn bộ mảng.

12. Cấp phát Bộ nhớ động

  • malloc: cấp phát một khối bộ nhớ có kích thước đã chỉ định và trả về con trỏ đến khối bộ nhớ đó.
  • calloc: tương tự như malloc, nhưng khởi tạo bộ nhớ bằng 0.
  • realloc: thay đổi kích thước của một khối bộ nhớ đã cấp phát.
  • free: giải phóng bộ nhớ đã cấp phát.

malloc

void* malloc(size_t kich_thuoc);

calloc

void* calloc(size_t so_phan_tu, size_t kich_thuoc);

realloc

void* realloc(void* chi_so, size_t kich_thuoc);

free

void free(void* chi_so);

Thẻ: C compiler preprocessor memory-management pointers

Đăng vào ngày 19 tháng 9 lúc 03:42