Khởi tạo các mảng con trỏ trong C

Xin chào các ngôi sao lập trình tương lai! Hôm nay, chúng ta sẽ cùng lặn sâu vào thế giới kỳ diệu của các mảng con trỏ trong C. Đừng lo lắng nếu bạn là người mới bắt đầu lập trình - tôi sẽ hướng dẫn bạn từng bước, giống như tôi đã làm cho hàng trăm sinh viên trong những năm dạy học của mình. Hãy lấy một cốc đồ uống yêu thích của bạn, và cùng bắt đầu hành trình thú vị này nhé!

C - Initialization of Pointer Arrays

Làm thế nào để khởi tạo mảng con trỏ trong C?

Trước khi chúng ta nhảy vào chi tiết của việc khởi tạo các mảng con trỏ, hãy nhanh chóng回顾 lại pointers là gì. Hãy tưởng tượng các con trỏ như những biển báo chỉ đường, chỉ đến các vị trí trong bộ nhớ của máy tính của bạn. Bây giờ, khi chúng ta nói về một mảng con trỏ, hãy nghĩ về nó như một hàng biển báo, mỗi biển báo chỉ đến một vị trí khác nhau.

Hãy bắt đầu với một ví dụ đơn giản:

int *ptr_array[5];

Dòng này khai báo một mảng chứa 5 con trỏ整数. Nhưng đợi đã! Chúng ta chỉ mới tạo ra các biển báo ở đây, chứ chưa phải dữ liệu mà chúng chỉ đến. Điều này giống như việc đặt các biển báo trống rỗng trong một thị trấn mới - chúng có đó, nhưng chúng chưa chỉ đến bất kỳ nơi nào hữu ích.

Để làm cho mảng con trỏ của chúng ta thực sự hữu ích, chúng ta cần khởi tạo nó. Dưới đây là cách chúng ta có thể làm điều đó:

int a = 10, b = 20, c = 30, d = 40, e = 50;
int *ptr_array[5] = {&a, &b, &c, &d, &e};

Trong ví dụ này, chúng ta đã tạo ra năm biến số nguyên và sau đó khởi tạo mảng con trỏ để chỉ đến các biến này. Điều này giống như chúng ta đãfinally viết các địa điểm trên các biển báo của mình!

Khởi tạo mảng con trỏ bằng từ khóa static

Bây giờ, hãy nói về từ khóa static. Trong C, static giống như một từ khóa ma thuật giúp các biến sống sót suốt đời của chương trình. Khi chúng ta sử dụng static với mảng con trỏ, nó đảm bảo rằng mảng chỉ được khởi tạo một lần và giữ giá trị của nó giữa các cuộc gọi hàm.

Dưới đây là một ví dụ:

static int *ptr_array[3] = {NULL, NULL, NULL};

Dòng này tạo ra một mảng tĩnh của ba con trỏ số nguyên, tất cả đều ban đầu chỉ đến NULL. Điều này giống như việc đặt ba biển báo vĩnh viễn trong thị trấn của chúng ta, nhưng chúng chưa quyết định nơi chúng nên chỉ đến.

Khởi tạo mảng con trỏ số nguyên

Hãy trở nên thực tế hơn một chút. Giả sử chúng ta muốn tạo một mảng con trỏ, mỗi con trỏ chỉ đến một số nguyên khác nhau. Dưới đây là cách chúng ta có thể làm điều đó:

int num1 = 10, num2 = 20, num3 = 30;
int *int_ptr_array[3] = {&num1, &num2, &num3};

for (int i = 0; i < 3; i++) {
printf("Giá trị tại int_ptr_array[%d]: %d\n", i, *int_ptr_array[i]);
}

Trong đoạn mã này, chúng ta đang tạo ra ba biến số nguyên và một mảng con trỏ chỉ đến các biến này. Sau đó, chúng ta sử dụng một vòng lặp để in ra các giá trị. Điều này giống như chúng ta đã đặt ba biển báo trong thị trấn của chúng ta, mỗi biển báo chỉ đến một ngôi nhà với một số khác nhau, và sau đó chúng ta đi du lịch qua thị trấn để đọc tất cả các số nhà!

Khởi tạo mảng con trỏ bằng địa chỉ trực tiếp

Đôi khi, chúng ta có thể muốn khởi tạo mảng con trỏ bằng các địa chỉ bộ nhớ trực tiếp. Mặc dù điều này ít phổ biến hơn, nhưng biết cách làm là rất hữu ích:

int *direct_addr_array[3] = {(int*)100, (int*)200, (int*)300};

for (int i = 0; i < 3; i++) {
printf("Địa chỉ trong direct_addr_array[%d]: %p\n", i, (void*)direct_addr_array[i]);
}

Trong đoạn mã này, chúng ta đang khởi tạo mảng với các địa chỉ bộ nhớ cụ thể. Điều này giống như chúng ta đang đặt các biển báo chỉ đến các tọa độ GPS cụ thể trong thị trấn của chúng ta. Tuy nhiên, hãy cẩn thận với cách tiếp cận này - việc chỉ đến các địa chỉ bộ nhớ ngẫu nhiên có thể rất nguy hiểm nếu bạn không biết chính xác mình đang làm gì!

Duyệt mảng bằng địa chỉ cơ sở

Bây giờ, hãy học một thủ thuật hay. Chúng ta có thể sử dụng phép toán con trỏ để duyệt qua một mảng chỉ bằng địa chỉ cơ sở. Dưới đây là cách làm:

int numbers[5] = {10, 20, 30, 40, 50};
int *base_ptr = numbers;  // base_ptr bây giờ chỉ đến phần tử đầu tiên của numbers

for (int i = 0; i < 5; i++) {
printf("Giá trị tại chỉ mục %d: %d\n", i, *(base_ptr + i));
}

Trong ví dụ này, base_ptr chỉ đến phần tử đầu tiên của mảng numbers. Bằng cách thêm i vào base_ptr, chúng ta có thể truy cập đến mỗi phần tử của mảng. Điều này giống như có một biển báo ma thuật có thể chỉ đến bất kỳ ngôi nhà nào trong thị trấn của chúng ta chỉ cần biết số bước để di chuyển!

Khởi tạo mảng con trỏ ký tự (chuỗi)

Mảng của các con trỏ ký tự thường được sử dụng để lưu trữ các chuỗi trong C. Dưới đây là một ví dụ:

char *fruits[] = {"Apple", "Banana", "Cherry", "Date", "Elderberry"};

for (int i = 0; i < 5; i++) {
printf("Quả %d: %s\n", i+1, fruits[i]);
}

Trong đoạn mã này, chúng ta đang tạo ra một mảng của các con trỏ ký tự, mỗi con trỏ chỉ đến một chuỗi ký tự. Điều này giống như chúng ta đã đặt các biển báo trong chợ nông sản của thị trấn, mỗi biển báo chỉ đến một quầy hàng trái cây khác nhau!

Khởi tạo mảng động của con trỏ

Cuối cùng, hãy nói về việc cấp phát bộ nhớ động cho mảng con trỏ. Điều này rất hữu ích khi chúng ta không biết kích thước của mảng tại thời điểm biên dịch:

int n = 3;  // Chúng ta có thể thay đổi giá trị này tại runtime
int **dynamic_ptr_array = (int**)malloc(n * sizeof(int*));

for (int i = 0; i < n; i++) {
dynamic_ptr_array[i] = (int*)malloc(sizeof(int));
*dynamic_ptr_array[i] = i * 10;
}

for (int i = 0; i < n; i++) {
printf("Giá trị tại dynamic_ptr_array[%d]: %d\n", i, *dynamic_ptr_array[i]);
}

// Đừng quên giải phóng bộ nhớ đã cấp phát!
for (int i = 0; i < n; i++) {
free(dynamic_ptr_array[i]);
}
free(dynamic_ptr_array);

Điều này giống như việc xây dựng một khu phố mới trong thị trấn của chúng ta theo yêu cầu. Chúng ta đầu tiên tạo ra các biển báo (dynamic_ptr_array), sau đó cho mỗi biển báo, chúng ta xây dựng một ngôi nhà (malloc(sizeof(int))) và đặt một số vào đó (i * 10). Sau khi chúng ta đã sử dụng xong khu phố, chúng ta đảm bảo dọn dẹp bằng cách giải phóng bộ nhớ đã cấp phát.

Và thế là xong, các bạn! Chúng ta đã cùng nhau hành trình qua thế giới của các mảng con trỏ trong C. Hãy nhớ, thực hành là cách tốt nhất để thành thạo, vì vậy đừng ngần ngại thử nghiệm với các khái niệm này. Chúc các bạn lập trình vui vẻ!

Credits: Image by storyset