C/C++中const指针的赋值规则:从“谁被保护”说起

在C/C++中,const关键字的核心作用是“保护数据不被意外修改”,但它与指针结合时,因修饰对象不同(指针本身、指针指向的内容),会产生完全不同的赋值规则。理解const与指针的组合,关键在于明确“谁被const修饰”——是指针指向的数据,还是指针本身。

一、指针与const的三种组合形式

指针与const结合有三种常见形式,我们通过声明示例来区分它们的含义:

声明形式含义(核心:const修饰谁?)通俗理解
const char* p;const修饰指针指向的内容(char),指针本身可修改“指向常量的指针”
char* const p;const修饰指针本身,指针指向的内容可修改“常量指针”(指针本身是常量)
const char* const p;const同时修饰指针本身和指向的内容,两者均不可修改“指向常量的常量指针”

二、不同形式的赋值规则详解

1. const char* p;(指向常量的指针)
  • 被保护的对象:指针指向的char类型数据(不能通过该指针修改内容)。

  • 可赋值的操作

    • 指针本身可以被重新赋值(指向其他地址)。
    • 可以指向常量字符串(如"hello")或普通字符串(但指向普通字符串时,仍不能通过该指针修改内容)。
  • 示例

    const char* p = "hello";  // 合法:指向常量字符串
    p = "world";              // 合法:指针重新指向其他地址
    char str[] = "test";
    p = str;                  // 合法:可以指向普通字符串(但不能修改其内容)
    
    // *p = 'H';  // 非法:不能通过p修改指向的内容(被const保护)
    
2. char* const p;(常量指针)
  • 被保护的对象:指针本身(指针一旦初始化,指向的地址不能改变)。

  • 可赋值的操作

    • 必须在声明时初始化(因为指针本身是常量,不能后续赋值)。
    • 可以通过指针修改指向的内容(只要内容不是const类型)。
  • 示例

    char str[] = "hello";
    char* const p = str;  // 合法:声明时必须初始化
    
    *p = 'H';             // 合法:可以修改指向的内容(str不是const)
    // p = "world";       // 非法:指针本身是常量,不能改变指向的地址
    
  • 注意:如果指向常量数据,即使指针本身是const,也不能修改内容:

    const char str[] = "hello";
    char* const p = str;  // 编译错误!普通指针不能指向const数据(权限放大)
    
3. const char* const p;(指向常量的常量指针)
  • 被保护的对象:指针本身和指向的内容(两者均不可修改)。

  • 可赋值的操作

    • 必须在声明时初始化(指针本身是常量)。
    • 既不能修改指针指向的地址,也不能修改指向的内容。
  • 示例

    const char* const p = "hello";  // 合法:声明时初始化
    
    // p = "world";       // 非法:指针本身是常量,不能改地址
    // *p = 'H';          // 非法:指向的内容是常量,不能修改
    

三、关键原则:权限不能放大

除了上述基本规则,const指针的赋值还需遵守“权限不能放大”原则:
允许将“常量数据的地址”赋值给“指向常量的指针”(权限不变),但不允许将“常量数据的地址”赋值给“普通指针”(权限放大,可能导致误修改)。

  • 合法示例(权限不变或缩小):

    const char* p1;
    char* p2 = "test";       // 注意:"test"是常量字符串,C++中此处实际应警告
    p1 = p2;                 // 合法:p2是普通指针,p1是指向常量的指针(权限缩小)
    
  • 非法示例(权限放大):

    const char* p1 = "hello";
    char* p2 = p1;           // 编译错误!p2是普通指针(可修改内容),p1指向常量(权限放大)
    

四、总结:哪些情况可以赋值?

指针类型能否修改指针指向的地址?能否修改指向的内容?必须声明时初始化?
const char* p;不能
char* const p;不能能(内容非const时)
const char* const p;不能不能

记住核心:const修饰谁,谁就不能被修改。指针本身的可修改性与指向内容的可修改性是独立的,由const的位置决定。在实际开发中,根据是否需要修改指针指向或内容来选择合适的const组合,既能保护数据安全,又能保证代码灵活性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐