const和指针

来源:互联网 发布:linux socket close 编辑:程序博客网 时间:2024/06/07 00:30

指针是C语言的一个特色,它是一把双刃剑。

指针提供了便捷的内存操作,同时也提升了程序的复杂度。

良好的编码习惯,有助于提升程序的健壮性。

const和指针

疑问

在阅读本文之前,请先看以下几个声明语句:

  int a = 10;  // #### 定义部分 ####  int const *d = &a; // 0  const int* b = &a; // 1  int* const c = &a; // 2  const int* const p = &a; // 3  const int const *p2 = &a; // 4

上述声明的指针变量,哪些指针是常量,哪些指针指向的内容是常量,或者哪些指针和其指向的内容都是常量?

有很多人写过博客来讨论const用于指针声明的情况,看完了之后,我仍然“记不住”。

因为大部分文章只是用程序run了一遍,告知结果,对应的分析并没有切中要害。也可能是这些分析没有对应我自身的问题点。

所以,凡事还是得躬行。

指针声明的语法

我们先从声明指针变量的语法来讲,一般声明一个指针变量的语法为:

type * p = xxx;
一般来讲,有两种写法:

  1. type* p = xxx;
  2. <pre name="code" class="cpp">type *p = xxx;
C语言是一个自由的语言,这两种形式在书写上都是符合要求的,而且一般人都倾向于将'*'写在靠近类型的一侧,也就是第一种声明方式,我自己也是如此。
这种声明方式的好处是,让人一下子就注意到这个变量是指向某种类型的指针。
但是,如果你对指针声明的知识理解的不到位的话,很多时候,采用第1种声明方式是有风险的。
比如以下这句
int* a, b, c;
就很容易造成误解。
有的人可能会误以为这是三个int型指针,而编码者本身的意图可能也是如此,但是事实并非如此。
它的含义是,a为指向int变量的指针, b和c均为一个int型变量。这会给维护代码的人带来困扰,因为他不知道编码者当初的本意。
如果采用方式2来声明的话,就会明显一点。
int *a, b, c;
一个解决的办法就是,每个变量都单独声明。但是,仅仅这样我们还没有理解到位。

解析

接下来,我们分解以下声明语句,之后大家就会有一个清晰的认识了。
其实,理解指针声明的关键在于理解这个'*'。
在这里,*是间接访问操作符,它只能间接引用指针变量;*a本身就是一个表达式,表示间接访问a指向的内存单元。

接下来,我们依据这个理念来理解const 指针的声明方式。

语句一

const int* b = &a;

它等价于

const int (*b) = &a;
  1. *b表明b是一个指针变量
  2. int (*b)表明通过b能够间接访问到一个整型变量,也就是说b为一个整型的指针
  3. const int (*b)则表明该整型变量是一个const常量。

所以,b是一个int类型的指针,它本身不是常量;它指向的整型变量为常量。

语句二

int* const c = &a;

它等价于

int *(const c) = &a;
  1. const c说明c是一个常量
  2. *(const c) 说明这个常量是一个指针
  3. 最后,int 关键字表明这个指针指向一个整型变量。

所以,c是一个int型指针,这个指针存储的地址值是常量,不可更改;c指向的整型内存单元不是常量,可更改。

语句三、四

它们是等价的,上述举例只是为了引出两种声明的写法。我们选其中一句来说明。

const int* const p1 = &a;
它等价于
const int (*(const p1)) = &a;
  1. const p1表明p1是一个常量;
  2. *(const p1)表明p1是一个指针;
  3. int *(const p1)表明p1是一个整型指针;
  4. const int *(const p1)则跟语句一是类似的,表明p1指向的内存单元也是一个常量。

所以,这里p1和p1指向的内存单元都是常量。

结束语

至此,用const来声明指针的几种情况均已经阐述完毕。其中,对于声明语句0我没有进行分解,日后留给自己复习检查用~
0 0
原创粉丝点击