Biến con trỏ cũng là một biến và cũng cần có địa chỉ, để lưu được địa chỉ của biến con trỏ bạn cần con trỏ cấp 2 hay con trỏ tới con trỏ.
1. Con Trỏ Cấp 2
Biến con trỏ cũng có địa chỉ riêng của nó, và nếu bạn muốn lưu giữ địa chỉ này thì bạn cần sử dụng con trỏ tới con trỏ.
Tương tự nếu bạn muốn lưu địa chỉ của con trỏ cấp 2 thì bạn cần con trỏ cấp 3, muốn lưu địa chỉ của con trỏ cấp 3 thì cần con trỏ cấp 4...
Số lượng dấu * trước tên biến sẽ thể hiện con trỏ là cấp 1, 2 , hay 3. Ví dụ *ptr là con trỏ cấp 1, **ptr là con con trỏ cấp 2 và ***ptr là con trỏ cấp 3
Ví dụ 1 : Con trỏ cấp 2
#include <math.h>
int N = 28;
int *ptr1 = &N; // con trỏ cấp 2 ptr2 lưu địa chỉ con trỏ ptr1
int **ptr2 = &ptr1;
cout << "Dia chi cua N : " << &N << endl;
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Dia chi cua ptr1 : " << &ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
cout << "Giai tham chieu ptr2 : " << *ptr2 << endl;
cout << "Giai tham chieu 2 lan ptr2 : " << **ptr2 << endl;
return 0;
}
Output :
Gia tri cua ptr1 : 0x6ffe14
Dia chi cua ptr1 : 0x6ffe18
Gia tri cua ptr2 : 0x6ffe18
Giai tham chieu ptr2 : 0x6ffe14
Giai tham chieu 2 lan ptr2 : 28
Chú ý code chạy trên máy của bạn sẽ có thể có output khác.
Giải thích :
Con trỏ ptr1 lưu địa chỉ của N là 0x6ffe14 hay giá trị của ptr1 là 0x6ffe14.
Con trỏ ptr2 trỏ tới ptr1 nên giá trị của ptr2 chính là địa chỉ của ptr1 là 0x6ffe18
Giải tham chiếu ptr2 sẽ giúp bạn truy xuất giá trị của biến mà ptr2 đang trỏ tới, mà ptr2 đang trỏ tới 1 nên giá trị khi giải tham chiếu ptr2 sẽ là ptr1 hay địa chỉ của N
Giải tham chiếu 2 lần sẽ giúp bạn truy xuất giá trị của N, giải tham chiếu lần 1 ta đang truy xuất tới ptr1, giải tham chiếu 2 lần sẽ truy xuất tới N
Ví dụ 2 : Con trỏ cấp 3
#include <math.h>
int N = 28;
int *ptr1 = &N; // con trỏ cấp 2 ptr2 lưu địa chỉ con trỏ ptr1
int **ptr2 = &ptr1;
int ***ptr3 = &ptr2;
cout << "Dia chi cua N : " << &N << endl;
cout << "Dia chi cua ptr1 : " << &ptr1 << endl;
cout << "Dia chi cua ptr2 : " << &ptr2 << endl;
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
cout << "Gia tri cua ptr3 : " << ptr3 << endl;
cout << "Giai tham chieu ptr3 : " << *ptr3 << endl;
cout << "Giai tham chieu 2 lan ptr3 : " << **ptr3 << endl;
cout << "Giai tham chieu 3 lan ptr3 : " << ***ptr3 << endl;
return 0;
}
Output :
Dia chi cua ptr1 : 0x6ffe00
Dia chi cua ptr2 : 0x6ffe08
Gia tri cua ptr1 : 0x6ffdfc
Gia tri cua ptr2 : 0x6ffe00
Gia tri cua ptr3 : 0x6ffe08
Giai tham chieu ptr3 : 0x6ffe00
Giai tham chieu 2 lan ptr3 : 0x6ffdfc
Giai tham chieu 3 lan ptr3 : 28
2. Hàm Và Con Trỏ Cấp 2
Để thay đổi giá trị của biến thông thường bằng hàm ta dùng con trỏ, vậy để thay đổi biến con trỏ ta cần cùng tới con trỏ cấp 2. Tương tự bạn muốn thay đổi giá trị của con trỏ cấp 2 thông qua hàm ta cần xây dựng tham số là con trỏ cấp 3.
Nhiều bạn nhầm tưởng để thay đổi giá trị của biến thông qua hàm chỉ cần sử dụng con trỏ, điều này chỉ đúng khi bạn muốn thay đổi giá trị của biến thông thường, còn thay đổi con trỏ thì không thể chỉ dùng con trỏ.
Ví dụ 1 : Thay đổi giá trị của con trỏ thông qua hàm
#include <math.h>
x = y;
}
int N = 28, M = 56;
int *ptr1 = &N;
int *ptr2 = &M;
cout << "Truoc khi goi ham : " << endl;
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
change(ptr1, ptr2);
cout << "Sau khi goi ham : \n";
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
return 0;
}
Output :
Gia tri cua ptr1 : 0x6ffe08
Gia tri cua ptr2 : 0x6ffe0c
Sau khi goi ham :
Gia tri cua ptr1 : 0x6ffe08
Gia tri cua ptr2 : 0x6ffe0c
Giải thích :
Hàm change nhận 2 tham số là ptr1 và ptr2, khi đó giá trị của con trỏ x = ptr1 và y = ptr2, trong hàm change gán con trỏ y cho con trỏ x. Nhưng vấn đề ở đây là ptr1 với x khác nhau và ptr2 với y khác nhau, chỉ đơn thuần ta gán giá trị của ptr1 và ptr2 cho x và y, do đó x y có thay đổi gì thì không ảnh hưởng tới ptr1 và ptr2. Do đó sau khi hàm change kết thúc thì không có gì thay đổi đối với ptr1 và ptr2.
Nếu bạn muốn thay đổi ptr1 thì bạn cần tìm nhờ hàm change tìm tới địa chỉ của ptr1 để thay thế, và khi đó thì ta cần con trỏ cấp 2 làm tham số cho hàm change.
Ví dụ 2 : Thay đổi con trỏ cấp 1 thông qua hàm bằng con trỏ cấp 2
#include <math.h>
*x = y;
}
int N = 28, M = 56;
int *ptr1 = &N;
int *ptr2 = &M;
cout << "Truoc khi goi ham : " << endl;
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
change(&ptr1, ptr2);
cout << "Sau khi goi ham : \n";
cout << "Gia tri cua ptr1 : " << ptr1 << endl;
cout << "Gia tri cua ptr2 : " << ptr2 << endl;
return 0;
}
Output :
Gia tri cua ptr1 : 0x6ffe18
Gia tri cua ptr2 : 0x6ffe1c
Sau khi goi ham :
Gia tri cua ptr1 : 0x6ffe1c
Gia tri cua ptr2 : 0x6ffe1c