Con Trỏ Thao Tác Với Mảng Hai Chiều Trong C
Có thể bạn quan tâm
Một mảng hai chiều là một mảng chứa nhiều mảng một chiều, đôi khi mảng hai chiều còn được ngầm hiểu như một bảng bao gồm các hàng và các cột. Mảng hai chiều còn thường được gọi với cái tên là ma trận có kích thước M x N (M là số hàng, N là số cột).
Truy cập vào phần tử trong mảng một chiều là việc truy cập vào hàng thứ i cột thứ j có trong mảng. Ví dụ mảng a[1][3] (nghĩa là: i = 1, j = 3)
Ví dụ dưới đây tôi có a là mảng 2 chiều (hay còn gọi là ma trận) có kích thước 3 x 3 như sau:
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} }; }Chúng ta có thể tưởng tượng mảng hai chiều trên như một bảng như sau:
Như ở trên ta vẫn thường gọi mảng có các hàng và các cột, tuy nhiên bộ nhớ của máy tính là tuyến tính và không có hàng và cột. Vì lý do đó nên các phần tử của mảng 2 chiều thực chất được lưu trữ theo một hàng và được gom nhóm lại theo các cột có trong hàng, xem hình minh họa dưới đây để hiểu rõ hơn:
Dòng trên cùng là số lượng các hàng, vì chúng ta có mảng 2 chiều kích thước 3 x 3 nên có 3 hàng (3 row). Trong mỗi hàng được gom nhóm lại 3 phần tử tương ứng với 3 cột.
Dòng ở giữa là giá trị của mỗi phần tử ở hàng thứ i cột thứ j, ví dụ tại a[1][3] = 3 (nghĩa là i = 1, j = 3) hay a[2][1] = 4 (nghĩa là i = 2, j = 1).
Dòng cuối cùng là địa chỉ của mỗi phần tử ở hàng thứ i cột thứ j, ví dụ a[1][1] lưu trữ tại địa chỉ 1000, a[1][2] lưu trữ tại địa chỉ 1004, a[1][3] lưu trữ tại địa chỉ 1008… và a[3][3] lưu trữ tại địa chỉ 1032
Vì đây là mảng có kiểu int và có kích thước 4 byte nên mỗi địa chỉ liền kề cách nhau 4 đơn vị (4 byte).
Chú ý: Địa chỉ ô nhớ trên chỉ là ví dụ để ta dễ hình dung.
2.Sử dụng con trỏ để thao tác với các phần tử trong mảng hai chiều2.1 Địa chỉ ô nhớ của các phần tử mảng hai chiều
Mảng hai chiều có thể được định nghĩa như là một con trỏ trỏ tới một nhóm các mảng một chiều liên tiếp nhau.
Ở mảng một chiều ta biết rằng tên của mảng chứa địa chỉ của mảng đó, hay phần tử a[0] (phần tử đầu tiên) cũng chứa địa chỉ của mảng đó.
Trong trường hợp của mảng 2 chiều, phần tử đầu tiên trong mảng 2 chiều lại chính là một mảng 1 chiều và nếu mảng hai chiều a có kích thước (3 x 3) và có địa chỉ tại phần tử đầu tiên (a + 0) là 1000 thì địa chỉ của phần tử thứ hai (a+1) là 1012 , địa chỉ tại phần tử thứ ba (a + 2) là 1024. Xem phần màu đỏ ở hình dưới đây:
Như vậy có nghĩa là:
- (a + 0) trỏ đến mảng thứ 0
- (a + 1) trỏ đến mảng thứ 1
- (a + 2) trỏ đến mảng thứ 2
Tóm lại, ta có thể hiểu (a + i) trỏ đến mảng một chiều thứ i trong mảng 2 chiều.
Tuy nhiên, trong mảng thứ i lại tồn tại thêm các giá trị ở trong đó (vì mảng thứ i này là mảng 1 chiều). Ví dụ (a + 0) thì sẽ là:
Hay (a + 1) thì sẽ là:
Hoặc (a + 2) thì sẽ là:
Chú ý: Địa chỉ ô nhớ trên chỉ là ví dụ để ta dễ hình dung.
2.2 Sử dụng con trỏ để truy cập địa chỉ và giá trị của phần tử mảng hai chiều
Bạn đọc hãy cùng tôi tham khảo hai ví dụ dưới đây để rút ra công thức tổng quát cho việc lấy địa chỉ và giá trị của mảng hai chiều a[i][j]
Ví dụ 1, giả sử tôi muốn lấy địa chỉ của a[0][0], nghĩa là tôi truy cập vào mảng 1 chiều đầu tiên, và truy cập tiếp theo vào phần tử đầu tiên trong mảng đó. Xem hình minh họa bên dưới
Tôi sẽ sử dụng cú pháp: *(a + 0) + 0 để lấy địa chỉ a[0][0]
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} }; //lay dia chi a[0][0] bang *(a + 0) + 0 printf("Dia chi cua a[0][0] la: %x", *(a + 0) + 0); }Dia chi cua a[0][0] la: 62fdf0 |
---|
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ụ thứ 2 tôi muốn lấy địa chỉ của a[2][1], nghĩa là tôi truy cập vào mảng 1 chiều thứ 2, và truy cập tiếp theo vào phần tử thứ 1 trong mảng đó.
Tôi sẽ sử dụng cú pháp: *(a + 2) + 1 để lấy địa chỉ a[2][1]
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}, }; //lay dia chi a[2][1] bang *(a + 2) + 1 printf("Dia chi cua a[2][1] la: %x", *(a + 2) + 1); }Dia chi cua a[2][1] la: 62fe0c |
---|
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
→ Qua hai ví dụ trên ta có thể rút ra công thức cho địa chỉ và giá trị của phần tử a[i][j] nào đó trong mảng 2 chiều
- Công thức cho địa chỉ ô nhớ a[i][j] là: *(a+i)+j
- Và ta hoàn toàn lấy được giá trị của a[i][j] bằng cách thêm toán tử * cho toàn bộ công thức trên: *(*(a+i) + j)
Để minh họa về việc lấy giá trị của chúng ta cùng quay lại ví dụ 2, tôi sẽ lấy giá trị tại a[2][1] = 8
Theo công thức *(*(a+2) + 1)
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}, }; //lay gia tri a[2][1] bang *(*(a+2) + 1) printf("Gia tri cua a[2][1] la: %d",*(*(a+2) + 1)); }Gia tri cua a[2][1] la: 8 |
---|
Như vậy, ta đã có công thức cho địa chỉ ô nhớ và giá trị của phần tử a[i][j] trong mảng hai chiều.
Tiếp theo ta sẽ áp dụng con trỏ để truy cập vào địa chỉ và giá trị của phần tử mảng a[i][j] đó. Ta nhớ lại rằng mảng 1 chiều khi thao tác với con trỏ ta chỉ việc gán con trỏ p = a (trong đó a là tên mảng) bạn đọc quên có thể quay lại đọc Bài 2: Con trỏ thao tác với mảng một chiều trong C.
Luôn nhớ rằng, mảng hai chiều thực chất cũng là mảng 1 chiều chứa nhiều phần tử và mỗi phần tử trong đó lại là một mảng 1 chiều gồm nhiều cột.
Vì thế để sử dụng con trỏ lưu trữ địa chỉ của mảng 2 chiều đó ta cần một con trỏ đến một mảng có kích thước bằng số cột của mảng 1 chiều.
Ví dụ dưới đây tôi có mảng a[3][3] (có 3 hàng 3 cột) nên tôi sẽ khai báo như sau:
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}, }; //khoi tao con tro p tro den 3 cot int (*p)[3]; //gan con tro p bang mang a p = a; }Giả sử tôi có mảng a[3][4] (3 hàng 4 cột) tôi sẽ khai báo: int (*p)[4];
→ Như vậy ta có công thức để có thể gán con trỏ cho mảng 2 chiều có kích thước a[i][j] là: int (*p)[j]
Bây giờ, ta hoàn toàn có thể sử dụng con trỏ để lấy giá trị và địa chỉ của các phần tử trong mảng a bằng cách:
- (p + i) để lấy ra địa chỉ của các phần tử trong mảng hai chiều
- * ( * ( p + i) + j ) để lấy ra giá trị của các phần tử trong mảng
Ví dụ dưới đây tôi sẽ sử dụng con trỏ (*p)[3] để lấy giá trị và địa chỉ của mảng a[3][3]
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}, }; //khoi tao con tro p int (*p)[3]; //gan con tro p bang mang a p = a; //duyet cac hang trong mang for(int i = 0; i < 3; i ++){ //hien thi dia chi cua tung phan tu trong mang 2 chieu printf("Dia chi phan tu %d la: %x \n",i , p + i); //duyet cac cot trong mang for(int j = 0; j < 3; j++){ //hien thi gia tri cua tung phan tu printf ("Gia tri: a[%d][%d] =%d \n" , i , j , * ( * ( p + i) + j ) ); } printf("\n \n"); } }Dia chi phan tu 0 la: 62fde0 Gia tri: a[0][0] =1 Gia tri: a[0][1] =2 Gia tri: a[0][2] =3 Dia chi phan tu 1 la: 62fdec Gia tri: a[1][0] =4 Gia tri: a[1][1] =5 Gia tri: a[1][2] =6 Dia chi phan tu 2 la: 62fdf8 Gia tri: a[2][0] =7 Gia tri: a[2][1] =8 Gia tri: a[2][2] =9 |
---|
Ví dụ 2 tôi sử dụng con trỏ (*p)[3] để lấy giá trị các phần tử là số chẵn có trong mảng a
#include <stdio.h> int main() { //khai bao mang 2 chieu a gom 3 x 3 phan tu int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9}, }; //khoi tao con tro p cho mang a[3][3] int (*p)[3]; //gan con tro p bang mang a p = a; printf("Cac phan tu trong mang la so chan \n"); //duyet cac hang trong mang for(int i = 0; i < 3; i ++){ //duyet cac cot trong mang for(int j = 0; j < 3; j++){ if(* ( * ( p + i) + j ) % 2 == 0){ //hien thi gia tri cac phan tu la so chan printf ("Gia tri: a[%d][%d] =%d \n" , i , j , * ( * ( p + i) + j ) ); } } } }Cac phan tu trong mang la so chan Gia tri: a[0][1] =2 Gia tri: a[1][0] =4 Gia tri: a[1][2] =6 Gia tri: a[2][1] =8 |
---|
Từ khóa » Khai Bao Mang 2 Chieu
-
Bài 54. Mảng 2 Chiều Trong C - Lập Trình Không Khó
-
5.3 Mảng Hai Chiều - Khóa Học C++
-
C Cơ Bản: Mảng 2 Chiều (Phần 1) - DevIOT
-
Mảng Hai Chiều Là Gì? Cách Khai Báo Và Khởi Tạo Trong C++
-
Mảng 2 Chiều Trong C
-
Mảng 2 Chiều Trong C - Học Lập Trình C Online - Viettuts
-
Mảng Hai Chiều - Mảng Đa Chiều Trong C++ - CodeLearn
-
Mảng 2 Chiều Trong C++ (Two-dimensional Arrays) | How Kteam
-
Mảng 2 Chiều 2d Array Trong C | Lập Trình Từ Đầu
-
Cách để Tạo Mảng Hai Chiều Trong Javascript
-
Mảng Hai Chiều
-
Khai Báo Mảng 2 Chiều Không Tường Minh By OpenStax (Page 3/4)
-
Cách Khai Báo Mảng 2 Chiều Trong C, C++