搞懂顶层const和底层const

c/c++

浏览数:201

2019-3-30

C语言虽然简单,但是重难点还是很多的,就比如让需要新手比较蛋疼的指针问题,但是深入学习之后指针才是碰到的第一个拦路虎,也是最简单的一个。比如声明问题,顶层const和底层const。今天说说后者。

声明问题可以理解为复杂指针,函数指针的声明和解读问题

int (*f(int, int))(int);
// f 是一个有两个int类型参数的函数,函数返回指向具有一个参数为int类型,返回类型为int的函数指针

以下有几个栗子

int iVal = 520;
// 第一个栗子
const int *pVal1 = &iVal;
// 第二个栗子
int const *pVal2 = &iVal;
// 第三个栗子
int * const pVal3 = &iVal;
// 第四个栗子
int const * const pVal4 = &iVal;

分析

首先我们说说顶层const和底层const的通俗定义
顶层const: 表示指针本身是个常量,更简单的说顶层const作用对对象本身,表示对象自身是一个常量
底层const: 表示指针所指向的对象是个常量

所以有以下结论(个人总结)

将const考虑成向右结合

  • 如果const右结合修饰的为类型或者*,那这个const就是一个底层const

  • 如果const右结合修饰的为标识符,那这个const就是一个顶层const

const的影响

2017-02-11 更新: 书写错误

int const * const p;
      ^       ^
      1       2
  • 底层const(上述代码中1的位置)主要影响的是指向的对象

    • 顶层const表示为不能修改所指向的对象的值,即,所指向的对象是一个常量。

  • 顶层const(上述代码中2的位置)主要影响的是对象本身

    • 表示对象本身不能被修改,即,对象(指针)本身是个常量,但是可以修改指针所指向的对象的值。

理解以上前提为要理解指针其实也是一个对象(int),这个对象的值是所要指向的对象的地址。
比如
对象 A 的地址 = 0x123456,对象 A 的值 = "ABCDEF"
指针 B 指向 对象 A
所以指针 B 的地址 = 0x234567, 指针 B 的值 = 0x123456
系统在栈或者堆中分配,因为指针本身是一个对象,也有属于自己的地址,所以可以有指向指针的指针
注意区别指针和引用

栗子分析

第一个和第二个栗子

const int *pVal1 = &iVal;
// const 右结合修饰 int ,所以这个const为底层const
int const *pVal2 = &iVal;
// const 右结合修饰 * ,所以这个const为底层const

第三个栗子

int * const pVal3 = &iVal;
// 这个const右结合修饰 pval3 ,修饰的是一个标识符,所以这个const为顶层const

第四个栗子

int const * const pVal4 = &iVal;
// 第一个const修饰的是 * 所以第一个const是底层const
// 第二个const修饰的是 pVal4 所以这个const是顶层const