Khái niệm
Con trỏ hằng (Pointer to Constant): Con trỏ trỏ đến dữ liệu không thể sửa đổi qua con trỏ đó. Dữ liệu được bảo vệ (read-only).
Cú pháp
const int *p; // Con trỏ TO hằng số int
int const *p; // Tương đương (thứ tự không quan trọng)
Quy tắc đọc: Đọc từ phải sang trái: *p là const int → p trỏ đến int const.
Chương trình minh họa
#include <stdio.h>
int main() {
int var = 100;
// Con trỏ đến hằng số
const int *ptr = &var;
printf("Gia tri qua con tro: %d\n", *ptr); // OK: Đọc
printf("Dia chi: %p\n", (void*)ptr);
// THỬ SỬA - SẼ LỖI COMPILE
// *ptr = 10; // Error: assignment of read-only location '*ptr'
// NHƯNG có thể sửa trực tiếp biến gốc
var = 200;
printf("Sau khi bien goc doi: %d\n", *ptr); // 200
// Con trỏ có thể trỏ chỗ khác
int other = 300;
ptr = &other; // OK: Thay đổi con trỏ
printf("Tro den other: %d\n", *ptr);
return 0;
}
Kết quả
Gia tri qua con tro: 100
Dia chi: 0x7ffc1234
Sau khi bien goc doi: 200
Tro den other: 300
So sánh 2 loại "Con trỏ const"
| Khai báo | Tên gọi | Giá trị (*p) | Địa chỉ (p) |
|---|---|---|---|
const int *pint const *p |
Pointer to Constant (Con trỏ đến hằng) |
KHÔNG sửa được | Sửa được |
int *const p |
Constant Pointer (Con trỏ hằng - địa chỉ cố định) |
Sửa được | KHÔNG sửa được |
const int *const p |
Constant Pointer to Constant | KHÔNG sửa được | KHÔNG sửa được |
Ví dụ: Constant Pointer (Con trỏ hằng - địa chỉ cố định)
#include <stdio.h>
int main() {
int a = 10, b = 20;
// Con trỏ HẰNG - phải khởi tạo ngay, không đổi địa chỉ được
int *const ptr = &a;
printf("Gia tri: %d\n", *ptr); // 10
*ptr = 99; // OK: Sửa giá trị tại địa chỉ
printf("Sau *ptr=99: a=%d\n", a); // a = 99
// ptr = &b; // LỖI COMPILE: assignment of read-only variable 'ptr'
return 0;
}
Ứng dụng thực tế: Pointer to Constant
1. Tham số hàm chỉ đọc (Const Correctness)
// Cam kết không sửa đổi mảng đầu vào
void inMang(const int *arr, int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
// arr[i] = 0; // LỖI compile - bảo vệ dữ liệu
}
}
// Có thể truyền cả mảng const và non-const
const int a[] = {1,2,3};
int b[] = {4,5,6};
inMang(a, 3); // OK
inMang(b, 3); // OK (non-const chuyển ngầm sang const)
2. Trả về con trỏ đến dữ liệu nội bộ (read-only)
const char* layThongBao(int maLoi) {
static const char *thongBao[] = {
"Thanh cong",
"Loi file",
"Loi bo nho",
"Loi mang"
};
return thongBao[maLoi]; // Trả về con trỏ đến hằng chuỗi
}
3. String literal tự động là const
char *s1 = "Hello"; // CẢNH BÁO: deprecated, string literal là const
const char *s2 = "Hello"; // ĐÚNG
// s1[0] = 'h'; // UNDEFINED BEHAVIOR - crash có thể xảy ra
Tóm tắt
const int *p: Dữ liệu const, con trỏ đổi được → Bảo vệ dữ liệuint *const p: Con trỏ const, dữ liệu đổi được → Bảo vệ địa chỉconst int *const p: Cả hai đều const- Luôn dùng
constcho tham số hàm chỉ đọc → Code an toàn, compiler tối ưu tốt hơn