Bài tập

Nhắc lại kiến thức mảng một chiều

Huy Erick

Mảng một chiều là một lưu trữ chứa những giá trị có cùng kiểu với nhau. Các phần tử của mảng được lưu trữ trong các vị trí liền kề nhau. Giả sử tôi có...

Mảng một chiều là một lưu trữ chứa những giá trị có cùng kiểu với nhau. Các phần tử của mảng được lưu trữ trong các vị trí liền kề nhau.

Giả sử tôi có một mảng a gồm 5 phần tử sẽ là:

#include  int main() {     int a[5] = {0,1,2,3,4}; }

Ta tưởng tượng các phần tử được lưu trữ trong mảng như sau:

Dòng trên cùng chính là phần truy cập vào vị trí trong mảng, dòng ở giữa chính là giá trị tại các vị trí mà dòng trên đang truy cập, dòng cuối cùng chính là địa chỉ của từng vị trí.

Nhận xét: Địa chỉ của các phần tử trong mảng là liền kề nhau. Ban đầu là địa chỉ 1000 khi truy cập vào phần tử sau đó (phần tử thứ 2) là 1004, truy cập vào phần tử thứ 3 là 1008 …. Truy cập vào phần tử cuối là 1016.

Vì kiểu int có kích thước là 4 byte nên mỗi lần truy cập vào địa chỉ phần tử liền kề trong mảng thì vị trí tăng lên 4 đơn vị (4 byte).

Như vậy ta có thể kết luận rằng các phần tử của một mảng được lưu trữ trong các vị trí bộ nhớ liền nhau.

2.1 Địa chỉ ô nhớ các phần tử mảng một chiều

Mảng một chiều, thực chất cũng tồn tại là một con trỏ. Trong đó, tên mảng chứa chính địa chỉ của mảng đó. Con trỏ đến phần tử đầu tiên của mảng cũng mang lại chính địa chỉ của mảng đó.

Để làm rõ hơn về điều này tôi có một ví dụ dưới đây, tôi khai báo một mảng a gồm 5 phần tử, tôi sẽ kiểm tra địa chỉ của mảng tại tên mảng và địa chỉ của con trỏ phần tử đầu tiên của mảng như sau:

#include  int main() {     //khai bao mang a gom 5 phan tu     int a[5] = {0,1,2,3,4};      //khai bao con tro p va gan p bang dia chi cua phan tu dau tien trong mang     int *p;     p = &a[0];      //hien thi ket qua     printf("dia chi ten mang %x\n", &a);     printf("dia chi cua con tro phan tu dau tien %x", p); }

Kết quả:

dia chi ten mang 62fe00 dia chi cua con tro phan tu dau tien 62fe00

Chú ý: Địa chỉ ô nhớ trên mỗi máy tính khi thực thi chương trình trên là khác nhau. Kết quả 62fe00 chỉ là kết quả minh họa.

Thực thi chương trình ta nhận thấy rằng, địa chỉ của tên mảng và địa chỉ của con trỏ phần tử đầu tiên trong mảng là như nhau.

Hiểu được địa chỉ ô nhớ của mảng để dễ dàng sử dụng con trỏ tương tác với mảng hơn.

2.2 Sử dụng con trỏ truy cập giá trị và địa chỉ của phần tử mảng một chiều

Sử dụng khái niệm đỉa chỉ ô nhớ của mảng một chiều ở phần trên, bây giờ ta có thể thao tác dễ dàng để truy cập vào giá trị và địa chỉ của mảng bằng các phép toán con trỏ.

Địa chỉ của một phần tử mảng có thể được biểu diễn theo hai cách:

  1. Sử dụng & trước phần tử mảng, ví dụ &a[i]
  2. Sử dụng biểu thức (a+i)

Xét ví dụ dưới đây tôi có mảng a gồm 5 phần tử, tôi sẽ lấy địa chỉ của từng phần tử trong mảng bằng &a[i] và vòng lặp for:

#include  int main() {     //khai bao mang a gom 5 phan tu     int a[5] = {0,1,2,3,4};      //lay dia chi cua tung phan tu     for(int i = 0; i  5; i++){         printf("Dia chi cua a[%d]: %x\n", i, &a[i]);     } }

Kết quả:

Dia chi cua a[0]: 62fe00 Dia chi cua a[1]: 62fe04 Dia chi cua a[2]: 62fe08 Dia chi cua a[3]: 62fe0c Dia chi cua a[4]: 62fe10

Chú ý: Địa chỉ ô nhớ trên mỗi máy tính khi thực thi chương trình trên là khác nhau. Kết quả trên chỉ là minh họa.

Ví dụ lần này tôi sẽ dùng (a+i) thay cho &a[i], kết quả thu được là tương tự:

#include  int main() {     //khai bao mang a gom 5 phan tu     int a[5] = {0,1,2,3,4};      //lay dia chi cua tung phan tu     for(int i = 0; i  5; i++){         printf("Dia chi cua a[%d]: %x\n", i, (a + i));     } }

Kết quả:

Dia chi cua a[0]: 62fe00 Dia chi cua a[1]: 62fe04 Dia chi cua a[2]: 62fe08 Dia chi cua a[3]: 62fe0c Dia chi cua a[4]: 62fe10

Qua 2 ví dụ trên ta đã biết cách lấy địa chỉ của từng phần tử có trong mảng, bây giờ ta có thể lấy giá trị của phần tử bằng cách khai báo con trỏ mảng và đặt biểu thức * trước địa chỉ cần lấy giá trị. (Nếu quên khái niệm này bạn đọc vui lòng đọc lại bài trước tôi đã giải thích về dấu * )

Chương trình dưới đây, tôi sẽ sử dụng con trỏ p gán bằng mảng a sau đó dùng con trỏ p để lấy ra các giá trị tại các địa chỉ của mỗi phần tử có trong mảng a:

#include  int main() {     //khai bao mang a gom 5 phan tu     int a[5] = {0,1,2,3,4};      //gan con tro p bang mang a     int *p;     p = a; // p = &a[0] cung giong nhu p = a      //lay gia tri va dia chi cua tung phan tu     for(int i = 0; i  5; i++){         printf("Gia tri cua a[%d] = %d ", i, *(p + i));         printf("Dia chi cua a[%d] = %x\n", i, (p + i));     } }

Kết quả:

Gia tri cua a[0] = 0 Dia chi cua a[0] = 62fdf0 Gia tri cua a[1] = 1 Dia chi cua a[1] = 62fdf4 Gia tri cua a[2] = 2 Dia chi cua a[2] = 62fdf8 Gia tri cua a[3] = 3 Dia chi cua a[3] = 62fdfc Gia tri cua a[4] = 4 Dia chi cua a[4] = 62fe00

Giải thích nhanh ví dụ trên:

  1. Gán con trỏ p = a hoặc có thể gán p = &a[0] hai điều này là giống nhau (xem lại phần Địa chỉ ô nhớ của mảng một chiều)
  2. Sử dụng toán tử *(p+i) để lấy giá trị của phần tử mảng tại vị trí thứ i
  3. Sử dụng biểu thức (p+i) để lấy địa chỉ của phần tử mảng tại vị trí i

Ví dụ tiếp theo tôi sử dụng con trỏ p để lấy ra địa chỉ các phần tử trong mảng a có giá trị là số chẵn:

#include  int main(){     //khai bao mang a gom 5 phan tu     int a[5] = {0,1,2,3,4};      //gan con tro p bang mang a     int *p;     p = a; // p = &a[0] cung giong nhu p = a      //lay gia tri va dia chi cua tung phan tu     printf("Gia tri va dia chi cac phan tu chan la: \n");     for(int i = 0; i  5; i++){         //kiem tra dieu kien neu gia tri *(p+i) % 2 ==0 thi hien thi ra dia chi va gia tri         if(*(p + i) % 2 == 0){             printf("Gia tri cua a[%d] = %d ", i, *(p + i));             printf("Dia chi cua a[%d] = %x\n", i, (p + i));         }     } }

Kết quả:

Gia tri va dia chi cua cac phan tu chan la:  Gia tri cua a[0] = 0 Dia chi cua a[0] = 62fdf0 Gia tri cua a[2] = 2 Dia chi cua a[2] = 62fdf8 Gia tri cua a[4] = 4 Dia chi cua a[4] = 62fe00

Ta nhận thấy rằng trong mảng a có các giá trị chẵn tại các chỉ số lần lượt là a[0], a[2], a[4], cách lấy giá trị theo con trỏ là *(p+0), *(p+2), *(p + 4) và cách lấy địa chỉ là (p + 0), (p + 2), (p + 4).

1