本文已参与「新人创作礼」活动,一起开启掘金创作之路。
关于到底谁是指针常量 、谁是常量指针,网上各种解释,我参考了《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. 什么是变量,指针?
内存其实是一个存放数据的空间,变量和指针都是内存中一小段空间的名字(根据数据类型的不同,变量和指针所占空间大小也不同),每个小空间都有自己的一个地址编号。变量所在的空间中存放的是普通数据;而指针比较特殊,其空间中存放的是特殊数据(另一段小空间的地址)。
我们可以对变量或指针赋值,这时它们的空间中的数据就会发生变化。
如果想在屏幕上显示地址,可以写如下代码: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 i
,const
与int
的相对位置对语义并无影响。如: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 = π // 指针ppi指向指针pi
ppi
的值—— 0X056,即指针pi 的地址。*ppi
的值——0X012,即指针pi 的值,也是变量i 的地址。通过解引用直接访问pi
的值**ppi
的值——10,即*pi
的值,也是变量i 的值。通过两次解引用直接访问 i 的值
今天的文章到底哪个是指针常量,哪个是常量指针?分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18959.html