Tiếp tục loạt bài trong series về con trỏ, trong bài này chúng ta sẽ tìm hiểu những nội dung sau:
- Hằng con trỏ (Constant pointer) là gì?
- Con trỏ hằng (Pointer to constant) là gì?
- Hằng con trỏ trỏ tới hằng (Constant pointer to constant) là gì?
1. Hằng con trỏ (Constant pointer) là gì?
■ Khai báo:
<Kiểu dữ liệu> * const <Tên con trỏ> = <Địa chỉ khởi tạo>;
■ Đặc điểm:
- Khi khai báo hằng con trỏ cần khởi tạo giá trị địa chỉ cho nó.
- Và từ lúc này, địa chỉ khởi tạo đó là cố định, không bao giờ thay đổi. Tức là: khi hằng con trỏ đã trỏ đến 1 địa chỉ, nó sẽ nằm “dính chặt” vào đó, không thể trỏ tới bất kỳ 1 địa chỉ nào khác.
- Có thể thay đổi được giá trị tại địa chỉ đã khởi gán ban đầu.
– Ví dụ 1: Lỗi khi hằng con trỏ p không được khởi tạo địa chỉ khi khai báo.
int main()
{
int* const p; // error
return 0;
}
[/code]
– Ví dụ 2: Lỗi khi thay đổi địa chỉ của hằng con trỏ.
int main()
{
int m = 2;
int* const p = &m;
p++; // error
return 0;
}
[/code]
– Ví dụ 3: Việc thay đổi giá trị là OK.
int main()
{
int m = 2;
int* const p = &m;
printf("\n*p = %d", *p);
// Thay đổi giá trị tại biến mà hằng con trỏ trỏ tới
m++; // OK
printf("\n*p = %d", *p);
// Thay đổi giá trị của hằng con trỏ
*p = 9; // OK
printf("\n*p = %d", *p);
getchar();
return 0;
}
[/code]
★ Từ đây ta có thể thấy tên mảng 1 chiều chính là một hằng con trỏ. Vì có thể thay đổi giá trị con trỏ arr trỏ tới, nhưng không thể thay đổi giá trị của arr.
int arr[5]; arr[0] = 5; // ok arr[9] = 1987; // ok arr++; // lỗi ko thể thay đổi arr--; // lỗi ko thể thay đổi
2. Con trỏ hằng (Pointer to constant) là gì?
■ Khai báo:
const <Kiểu dữ liệu> * <Tên con trỏ>;
■ Đặc điểm:
- Con trỏ hằng có thể trỏ đến các ô nhớ khác nhau (có thể trỏ đi lung tung trong bộ nhớ, các phép toán tăng giảm địa chỉ của con trỏ hoàn toàn hợp lệ).
- Nhưng không thể thay đổi giá trị tại ô nhớ mà nó đang trỏ đến.
Có thể bạn quan tâm: Cách cấp phát và giải phóng bộ nhớ trong lập trình C.
* Các bạn có thể nhận thấy nó ngược với hằng con trỏ đã nói ở trên.
* Ví dụ điển hình là hàm strlen mà chúng ta hay sử dụng để lấy chiều dài của một chuỗi:
size_t strlen ( const char * str );
– Ví dụ 1: Con trỏ hằng có thể thay đổi địa chỉ mà nó trỏ tới.
int main()
{
int num1 = 2;
int num2 = 10;
char *blog = "minhhn.com";
const int *p;
p = &num1;
printf("\nGia tri nhan duoc: %d", *p); // Output: 2
p = &num2;
printf("\nGia tri nhan duoc: %d", *p); // Output: 10
p = blog;
printf("\nGia tri nhan duoc: %s", p); // Output: minhhn.com
getchar();
return 0;
}
[/code]
– Ví dụ 2: Con trỏ hằng không thể thay đổi giá trị của địa chỉ mà nó trỏ tới.
int main()
{
int m = 3;
const int *p;
p = &m;
m = 20; // ok
m++; // ok
*p = 99; // error
(*p)++; // error
return 0;
}
[/code]
★ Khi bạn code trong 1 project C lớn một tí hoặc lớn nhiều tí, giả sử bạn có 1 hàm, thao tác với 1 mảng, hàm này chỉ đọc mảng thôi, không làm thay đổi các giá trị trong mảng. Và quan trọng là, khi share code cho các bạn khác trong cùng project, làm sao để họ biết điều này???
Vậy ta sẽ cài đặt hàm của mình như sau:
/*
Đối với trường hợp con trỏ hằng là tham số thì:
void Xuly(const int *) và void Xuly(int const *)
là như nhau, từ const khi đóng góp vào trong tham số hình thức là như nhau.
*/
void Xuly(const int *a, int n)
{
// Xử lý gì đó
}
int main()
{
int a[] = { 1,2 };
int n = 2;
Xuly(a, n); // Khi sử dụng hàm này tôi hiểu là: nó ko thay đổi các giá trị mảng a của tôi đâu
// yên tâm xài, nếu có lỗi gì đó thì ko phải sinh ra từ đây.
return 0;
}
[/code]
3. Hằng con trỏ trỏ tới hằng (Constant pointer to constant) là gì?
■ Khai báo:
const <Kiểu dữ liệu> * const <Tên con trỏ> = <Địa chỉ khởi tạo>;
■ Đặc điểm:
- Không thể thay đổi được địa chỉ mà con trỏ trỏ tới.
- Và cũng không thể thay đổi được giá trị tại địa chỉ mà con trỏ trỏ tới.
int main()
{
int m = 44;
int n = 55;
const int* const p = &m;
p = &n; // error: Không thể thay đổi địa chỉ
*p = 100; // error: Không thể thay đổi giá trị
return 0;
}
[/code]
[…] tương đương với arr). Thật vậy, tên mảng một chiều thực chất là một con trỏ hằng trỏ tới địa chỉ của phần tử đầu tiên trong […]
[…] – Size = 4 : Sau khi thực hiện hàm ResizeArray thì không làm thay đổi kích thước của mảng, vì mảng một chiều chính là một hằng con trỏ, chỉ có thể thay đổi được giá trị, nhưng không thể thay đổi được (không tăng hay giảm được) kích thước vùng nhớ, xem thêm: Thế nào là hằng con trỏ? […]