从混淆到精通:C/C++常量指针与指针常量的本质差异与实战应用

发布于:2025-03-01 ⋅ 阅读:(11) ⋅ 点赞:(0)

一、定义与声明

  1. 常量指针(Pointer to Constant)

    • 定义:指针指向的内容为常量,不可通过该指针修改,但指针本身可改变指向。
    • 声明方式:const int* pint const* p
      const int a = 10;
      const int* p = &a;  // p是常量指针 
      // *p = 20;         // 错误!内容不可修改 
      p = &b;             // 正确,指针指向可修改 
      
  2. 指针常量(Constant Pointer)

    • 定义:指针本身是常量,不可修改指向的地址,但可通过指针修改指向的内容。
    • 声明方式:int* const p
      int b = 20;
      int* const p = &b;  // p是指针常量 
      *p = 30;            // 正确,内容可修改 
      // p = &a;          // 错误!指针指向不可修改 
      
  3. 常指针常量(Constant Pointer to Constant)

    • 定义:指针本身和指向的内容均为常量。
    • 声明方式:const int* const p
      const int c = 30;
      const int* const p = &c;  // 两者均不可修改 
      // *p = 40;               // 错误!
      // p = &a;                // 错误!
      

二、核心区别对比

特性 常量指针 指针常量 常指针常量
指针指向可变性 可修改指向(p = &b 不可修改指向 不可修改指向
内容可变性 不可通过指针修改内容 可通过指针修改内容 不可通过指针修改内容
初始化要求 无强制初始化 必须初始化 必须初始化
典型应用场景 函数参数保护数据 固定地址操作硬件/资源 完全不可变的全局配置

三、使用场景与注意事项

  1. 常量指针的典型应用

    • 函数参数保护:避免函数内部修改外部数据,如strlen(const char* s)
    • 指向字面量:如const char* str = "Hello";,防止修改字符串常量。
  2. 指针常量的典型应用

    • 硬件寄存器操作:固定地址的硬件寄存器访问,如volatile int* const reg = 0x8000;
    • 资源句柄管理:如文件指针需固定指向某个资源句柄。
  3. 常见错误

    • 混淆声明顺序:int const* pconst int* p等价,但int* const p完全不同。
    • 未初始化指针常量:int* const p;会导致编译错误。
    • 通过常量指针修改数据:需确保原始变量本身不是常量(如const int a不可修改,但int a可通过其他方式修改)。

四、示例代码解析

#include <iostream>
using namespace std;
 
int main() {
    int x = 10, y = 20;
    
    // 常量指针 
    const int* p1 = &x;
    // *p1 = 15;    // 编译错误 
    p1 = &y;        // 合法 
 
    // 指针常量 
    int* const p2 = &x;
    *p2 = 15;       // 合法 
    // p2 = &y;     // 编译错误 
 
    // 常指针常量 
    const int* const p3 = &x;
    // *p3 = 20;    // 错误 
    // p3 = &y;     // 错误 
    return 0;
}

五、记忆技巧

  1. 从右向左读声明:
    • const int* p → “p是指针,指向int常量”。
    • int* const p → “p是常量,指向int”。
  2. 口诀:
    • 常量指针:内容不变,指向可变(如看门狗,只读不写)。
    • 指针常量:指向不变,内容可变(如固定管家,可改内容)。