Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình C

Con trỏ hằng (Pointer to Constant) trong C

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 *p
int 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ệu
  • int *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 const cho tham số hàm chỉ đọc → Code an toàn, compiler tối ưu tốt hơn