到底哪个是指针常量,哪个是常量指针?

到底哪个是指针常量,哪个是常量指针?本文已参与「新人创作礼」活动,一起开启掘金创作之路。 关于到底谁是指针常量 、谁是常量指针,网上各种解释,我参考了《C++ primer》、《C和指针》等经典书籍。总结如下:

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

关于到底谁是指针常量 、谁是常量指针,网上各种解释,我参考了《C++ primer》、《C和指针》等经典书籍。总结如下:

int const * a :a是指针常量(指向常量的指针)! 指针指向地址的值是不变的。

int * const b :b是常量指针! 指针指向的地址是不变的,但是他的内容可变。

举个例子:

// 常量指针
int i = 10; 
int *const j = &i; // 指针 j 本身是不可以修改的,但是 *j 可以修改。

// 指针常量(指向常量的指针)
int i = 10;
int z = 20;
int const* j = &i; // 指针 j 本身可以修改,但是 *j 不可以修改。

巧记:是指针常量还是常量指针,从右往左读! const关键字后面的是不可修改的。

以下是加餐内容,从零开始介绍指针。


1. 什么是变量,指针?

内存其实是一个存放数据的空间,变量和指针都是内存中一小段空间的名字(根据数据类型的不同,变量和指针所占空间大小也不同),每个小空间都有自己的一个地址编号。变量所在的空间中存放的是普通数据;而指针比较特殊,其空间中存放的是特殊数据(另一段小空间的地址)。

image-20210519175220968

我们可以对变量或指针赋值,这时它们的空间中的数据就会发生变化。

如果想在屏幕上显示地址,可以写如下代码:printf("%x", &i);。(这里显示出的地址是虚拟地址而非变量实际的物理地址)

最后总结代码:

int a; // 向内存中申请了一个名为a的整型变量宽度的空间
int* pa; // 向内存中申请了一个名为pa的空间
a = 10; // 将10装入名为a的空间中
pa = &a; // pa中存放a的地址
*pa = 20; // 通过解引用直接访问a的空间,将原来a中的10换为20
printf("%d", a) // 输出20

2. 指针和数组名

首先,数组名其实就是一个特殊的指针。我们一般所认识的如int* pa是一个指针变量,而如数组int a[] = {1, 2, 3}; 数组名a是一个常量指针。既然数组名 a 是常量指针,其值是不能修改的,因此不能类似这样的操作:a++

int *pa, a[] = {3,4,5};
pa = a;
for (int i = 0; i <= 2; i++) {
    printf("%d\n", *pa);
    pa++; /*注意这里,指针值被修改*/
}
// 上面代码可以成功运行。
// 下面代码将会编译出错。
int *pa, a[] = {3,4,5};
pa = a;
for (int i = 0; i <= 2; i++) {
    printf("%d\n", *a);
    a++; /*注意这里是数组名*/
}

3. 区分const int *pi与int *const pi

记住,对于int const iconstint 的相对位置对语义并无影响。如:const int *pi等价于int const *pi

int i 说起,我们可以对变量i 的空间放入任何允许范围内的数据。在加入关键字 const 后,即const int i,就相当于给变量i 的空间上了一把锁,我们再不能随意更改数据了。

现在来看const int *pi

int i1 = 10;
int i2 = 40;
const int *pi = &i1;
pi = &i2; // 一切正常,注意,这里pi还是可以随意重新赋值,限制的只是*pi
*pi = 80; // !!!将会报错!!!
i2 = 80; // 一切正常哈哈,这时printf("%d", *pi); 将输出80

什么原因呢?

首先 const 修饰的是整个*pi。所以*pi是常量,是不能被赋值的(虽然pi所指的 i2 是变量,不是常量)

其次,pi 前并没有用const 修饰,所以pi是指针变量,能被赋值重新指向另一内存地址。

再来看int *const pi

int i1 = 10;
int i2 = 40;
int *const pi = &i1;
pi = &i2; // !!!将会报错!!!
*pi = 80; // 一切正常,这时printf("%d", i1); 将输出80

什么原因呢?

pi 因为有了const 的修饰,所以只是一个常量指针:也就是说pi值是不可修改的(即pi不可以重新指向 i2 这个变量了)。

整个*pi的前面没有const 的修饰。也就是说,*pi是变量而不是常量,所以我们可以通过*pi来修改它所指内存 i1 的值。

4. 函数参数的传递

(直接看书,P20-P29)

C语言中函数参数的传递有:值传递、地址传递、引用传递这三种形式。

注意函数调用时的 隐含赋值操作

  • 值传递的函数里的操作不是实参本身,只是将原变量的值赋给了形参,函数里操作的是形参。
  • 地址传递是将实参的地址传入函数中,在函数中通过解引用对实参进行操作。
  • 引用传递的函数中操作的就是实参本身。

5. 指向另一指针的指针

直接看代码、看图:

short int i = 10;
short int *pi = &i; // 指针pi指向变量i
short int **ppi = &pi; // 指针ppi指向指针pi

image-20210519201843189

  • ppi的值—— 0X056,即指针pi 的地址。
  • *ppi的值——0X012,即指针pi 的值,也是变量i 的地址。通过解引用直接访问pi的值
  • **ppi的值——10,即*pi 的值,也是变量i 的值。通过两次解引用直接访问 i 的值

今天的文章到底哪个是指针常量,哪个是常量指针?分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18959.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注