Con trỏ và Mảng đa chiều trong C

Xin chào các siêu sao lập trình tương lai! ? Tôi rất vui được làm hướng dẫn viên của bạn trong hành trình thú vị qua thế giới của các con trỏ và mảng đa chiều trong C. Là người đã dạy lập trình trong nhiều năm, tôi có thể đảm bảo với bạn rằng mặc dù những khái niệm này có thể看起来 phức tạp ban đầu, nhưng chúng thực sự rất thú vị một khi bạn nắm vững. Hãy cùng bắt đầu nào!

C - Pointers vs. Multi-dimensional Arrays

Con trỏ và Mảng một chiều

Trước khi chúng ta chuyển sang mảng đa chiều, hãy bắt đầu với những điều cơ bản: con trỏ và mảng một chiều. Hai khái niệm này có liên quan mật thiết với nhau trong C, và việc hiểu mối quan hệ này là rất quan trọng.

Con trỏ là gì?

Con trỏ là một biến lưu trữ địa chỉ bộ nhớ của một biến khác. Hãy nghĩ của nó như một biển báo chỉ đến nơi dữ liệu được lưu trữ trong bộ nhớ của máy tính của bạn. Dưới đây là cách chúng ta宣布 và sử dụng một con trỏ:

int number = 42;
int *ptr = &number;

printf("Giá trị của number: %d\n", number);
printf("Địa chỉ của number: %p\n", (void*)&number);
printf("Giá trị của ptr: %p\n", (void*)ptr);
printf("Địa chỉ mà ptr đang chỉ đến: %d\n", *ptr);

Trong ví dụ này, ptr là một con trỏ giữ địa chỉ của number. Оператор & cho chúng ta địa chỉ của một biến, và оператор * (khi sử dụng với một con trỏ) cho chúng ta giá trị tại địa chỉ đó.

Mảng và Con trỏ

Bây giờ, hãy xem điều thú vị. Trong C, tên của một mảng thực sự là một con trỏ đến phần tử đầu tiên của nó! Hãy cùng xem điều này trong hành động:

int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;  // Không cần &, arr đã là một con trỏ rồi!

printf("Phần tử đầu tiên sử dụng cách viết mảng: %d\n", arr[0]);
printf("Phần tử đầu tiên sử dụng cách viết con trỏ: %d\n", *p);

// Chúng ta có thể sử dụng phép toán con trỏ để truy cập các phần tử khác
printf("Phần tử thứ ba sử dụng phép toán con trỏ: %d\n", *(p + 2));

Đó có phải không tuyệt vời không? Chúng ta có thể sử dụng arr như thể nó là một con trỏ vì, theo một cách nào đó, nó就是这样!

Con trỏ và Mảng hai chiều

Bây giờ chúng ta đã có nền tảng cơ bản, hãy nâng cấp một chút với mảng hai chiều. Đây là những khái niệm như bảng hoặc lưới, với hàng và cột.

Khai báo một Mảng 2D

Dưới đây là cách chúng ta宣布 và khởi tạo một mảng 2D:

int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};

Điều này tạo ra một lưới 3x4 của các số nguyên. Nhưng làm thế nào điều này liên quan đến con trỏ?

Mảng 2D và Con trỏ

Một mảng 2D thực sự là một mảng của các con trỏ, nơi mỗi con trỏ chỉ đến một mảng 1D. Hãy phân tích nó:

int (*p)[4] = matrix;

printf("Phần tử đầu tiên: %d\n", matrix[0][0]);
printf("Cùng phần tử sử dụng con trỏ: %d\n", **p);

// Truy cập các phần tử khác
printf("Phần tử tại hàng 1, cột 2: %d\n", matrix[1][2]);
printf("Cùng phần tử sử dụng con trỏ: %d\n", *(*(p + 1) + 2));

Trong ví dụ này, p là một con trỏ đến một mảng 4 số nguyên. Mỗi p + i cho chúng ta một con trỏ đến một hàng, và sau đó chúng ta có thể truy cập các phần tử trong hàng đó.

Con trỏ và Mảng ba chiều

Chuẩn bị cho kẻ thù cuối cùng? Mảng ba chiều! Đây là những khái niệm như chồng các mảng 2D. Hãy tưởng tượng một khối được làm từ các số.

Khai báo một Mảng 3D

Dưới đây là cách chúng ta宣布 và khởi tạo một mảng 3D:

int cube[2][3][4] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}},
{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}
};

Điều này tạo ra một khối 2x3x4 của các số nguyên.

Mảng 3D và Con trỏ

Giống như với mảng 2D, chúng ta có thể sử dụng con trỏ để điều hướng mảng 3D của chúng ta:

int (*p)[3][4] = cube;

printf("Phần tử đầu tiên: %d\n", cube[0][0][0]);
printf("Cùng phần tử sử dụng con trỏ: %d\n", ***p);

// Truy cập các phần tử khác
printf("Phần tử tại lớp 1, hàng 2, cột 3: %d\n", cube[1][2][3]);
printf("Cùng phần tử sử dụng con trỏ: %d\n", *(*(*(p + 1) + 2) + 3));

Ở đây, p là một con trỏ đến một mảng 3x4 của các số nguyên. Mỗi cấp độ của * rút ngắn một chiều của mảng.

Kết luận

Uf! Chúng ta đã bao quát rất nhiều nội dung, từ các con trỏ đơn giản đến các mảng 3D phức tạp. Nhớ rằng, chìa khóa để thành thạo những khái niệm này là thực hành. Hãy thử viết mã của riêng bạn, thử nghiệm với các kích thước mảng khác nhau, và đừng sợ mắc lỗi - đó là cách chúng ta học hỏi!

Dưới đây là bảng tham khảo nhanh các cách viết con trỏ mà chúng ta đã bao quát:

Loại Mảng Khai báo Cách viết Con trỏ
Mảng 1D int arr[5] int *p = arr
Mảng 2D int arr[3][4] int (*p)[4] = arr
Mảng 3D int arr[2][3][4] int (*p)[3][4] = arr

Tiếp tục lập trình, tiếp tục khám phá, và nhớ - mỗi chuyên gia đều từng là người mới bắt đầu. Bạn làm được! ??️

Credits: Image by storyset