Giới thiệu
Các hiểu nhầm thường thấy khi làm việc với con trỏ là giá trị và địa chỉ của con trỏ, vì giá trị của con trỏ chứa địa chỉ có thể là của 1 biến khác, 1 vùng nhớ chứ dữ liệu hay địa chỉ của hàm, dẫn đến phát sinh lỗi trong quá trình viết mã nguồn. Trong đó, còn 1 vấn đề khác nữa là phân biệt con trỏ hằng và hằng con trỏ.
Nhắc lại về con trỏ
Giả sử có 3 biến con trỏ p
, q
, r
có địa chỉ lần lượt là 0x0110
, 0x0114
, 0x0118
trỏ đến vùng nhớ có địa chỉ 0x0024
lưu giá trị 79
. Trong trường hợp này có thể thay đổi giá trị của vùng nhớ 0x0024
thông qua con trỏ p
, q
, r
.
Có lúc nhu cầu chỉ là tham chiếu đến giá trị để sử dụng và không có nhu cầu thay đổi giá trị này, thậm chí việc thay đổi giá trị này cũng làm cho tính năng chạy sai.
Từ đó cần 1 ràng buộc con trỏ hoặc vùng nhớ được tham chiếu đến là không được phép thay đổi và con trỏ hằng và hằng con trỏ được giới thiệu.
Con trỏ hằng
Cú pháp khai báo con trỏ hằng:
const <kiểu dữ liệu> *<tên biến> = địa chỉ mà con trỏ trỏ đến
Con trỏ hằng là con trỏ trỏ đến một địa chỉ mà không thể thay đổi giá trị lưu ở địa chỉ mà nó trỏ đến, nhưng việc thay đổi giá trị của con trỏ vẫn hợp lệ.
Ví dụ:
int main() { int a = 10; int b = 11; const int *p = &a; *p = 100; // Không hợp lệ p = &b; // Hợp lệ return 0; }
Hằng con trỏ
Cú pháp khai báo hằng con trỏ:
<kiểu dữ liệu>* const <tên biến> = địa chỉ mà con trỏ trỏ đến.
Hằng con trỏ là con trỏ trỏ đến một địa chỉ cố định, giá trị của con trỏ không được phép thay đổi, nhưng có thể thay đổi giá trị của vùng nhớ mà con trỏ trỏ đến.
Ví dụ:
int main() { int a = 10; int b = 11; int* const p = &a; *p = 100; // Hợp lệ p = &b; // Không hợp lệ return 0; }
Sử dụng kết hợp con trỏ hằng và hằng con trỏ
Sử dụng kết hợp cả 2 tính năng trên sẽ được 1 kết quả là con trỏ không được phép thay đổi giá trị của nó lẫn giá trị vùng nhớ mà nó đang trỏ đến.
int main() { int a = 10; int b = 11; const int* const p = &a; *p = 100; // Không hợp lệ p = &b; // Không hợp lệ return 0; }