前言:
距离上一次更新关于初识指针的内容已经有一段时间了,本文旨在继续深入探讨指针的相关知识。在引入新的知识点之前,让我们先对之前介绍过的内容进行一个简要的回顾。
上一篇中我们主要介绍了内存和地址,什么是指针、指针变量,指针类型以及void*的用法
知识回顾:
1.内存和地址:内存类似宿舍楼,房间是内存单元,数据是房间里的人,门牌号是地址,计算机通过地址管理内存,编址由硬件设计完成。
2.指针变量和地址:通过(&)取地址操作符获取地址,可将地址存储在指针变量中,指针类型如int ,解引用操作符(*)用于操作指针指向的对象,指针变量大小取决于地址大小,与指针类型无关。
3.指针变量类型的意义:指针类型决定了解引用时的权限和指针移动的距离。
4.void*指针:可以接受任意类型地址,但不能直接进行指针运算,常用于存放地址并通过强制类型转换进行解运算。
接下来这篇文章将会讲到一个关键字const,指针运算,以及指针的使用和传址调用
1、const
const是一个关键字,一般用来做两件事:
- const修饰普通变量
- const修饰指针变量
1.1 const修饰普通变量
#include <stdio.h>
int main()
{
int n = 0;//变量初始化
n = 20;//修改变量的值
printf("%d\n", n);
return 0;
}
结果:原来是0的值可以修改为20.这就是变量
如果加上const呢?const int n = 0;
当被const修饰后,该程序就无法实现了,为什么呢?
const被称为长属性—被const修饰后的变量就具有长属性,长属性的意思就是不能被修改。
但是如果我们不修改变量的值,直接使用是否可以?
int main()
{
const int n = 0;
//n = 20;
printf("%d\n", n);
return 0;
}
结果肯定是可以的,被const修饰的变量可以打印,但是当你要修改它的值的时候,程序就无法实现了。
那么被const修改后的变量被认为是变量还是常量呢?
在C语言中,被const修饰后的变量被称为长变量,它的本质还是变量,因为有const修饰,编译器在语法上不允许修改这个变量。
在c++语言中,被const修饰后的变量被称为常量。
知道这个有什么用呢?
在C99之前,编译器是不支持变长数组作为数组大小的,因此,这里由于n的本质还是变量,因此无法实现(在C语言上)
如果我们改为**c++**呢?
当我们将文件后缀改为c++后,由于在c++中,被const修饰的变量的本质是常量,所以这里数组的大小就可以使用 n 来表示。
作用:当以后你写一个变量但是不希望别人修改的话,就可以使用const来修饰
注意:const位置放在函数类型(int)的前面或者后面都是可行的,不过习惯上我们都放在前面。
1.2 const修饰指针变量
前面我们说被const修饰后的变量不能被修改,但是如果我们就想要去修改并且还并不想删去const,该怎么办呢?
#include <stdio.h>
int main()
{
const int n = 0;
//n = 20;
int* p = &n;
*p = 20;
printf("%d\n", n);
return 0;
}
上诉代码中,我们通过取到n的地址来修改n的值,是否可行呢?
我们发现可以修改了。
不过,虽然我们得到了想要的结果,但是你们有没有觉得上诉代码有一些奇怪?
我们为什么要在变量n前面加上const呢?不就是为了防止变量n的值被修改吗?但是这里我们又通过指针的方式将n的值修改。这就像现实生活中,我这里有一个房子,你不能翻窗户进去,只能从正门进去,但是某一天呢,我有事不在家,就把房门锁上了,你无法从正门进去了,于是你把窗户砸了,从窗户爬进去了。
上面通过指针的操作就破坏了const修饰变量的目的。
为了防止这种情况,我们就需要用const来修饰指针变量。
我们应该怎么做呢?
const修饰指针变量有三种方式:
int * pconst可以放在的左边,也可以放在的右边,也可以左右两边都放上const
不管是const int * p 还是int const * p 都算放在*的左边
三种情况:
1.const放在*的左边:int const * p2.const放在*的右边:int * const p
3.comst放在*的两边:const int * const p
1. const放在*的左边:int const * p
关于对 p 的理解
int n = 10;
int p = &n;*
p里存放的是n的起始地址,通过p可以找到n,如果像修改n的值,我们无非就是两种方式
一种通过修改p的值来修改n:p = &m ,通过将m的地址给到p,然后修改n的值
另一种通过p找到n来直接修改n的值:*p = 200;
当我们能够对p有这样的理解后,我们在来看 const放在的左边的时候,限制的是p变量本身,还是*p指向的内容。
代码展示:
#include <stdio.h>
int main()
{
const int n = 0;
int m = 100;
const int* p = &n;
p = &m; //可行
*p = 100;//不可行
printf("%d\n", n);
return 0;
}
可以看到p = &m;是可执行的,而*p = 100;则会报错。
所以当const放在的左边的时候,限制的是p,也就是说不能通过p找到n的值来修改n的值
const放在*的左边的意思是:表示指针指向的内容,不能通过指针来改变了,按时指针变量本身的值是可以改的。
2. const放在*的右边:int * const p
int main()
{
const int n = 0;
int m = 100;
int* const p = &n;
p = &m; //不可行
*p = 100;//可行
printf("%d\n", n);
return 0;
}
当const放在的右边后, p = &m是无法执行的。而p = 100则是可以执行的。说明const放在*的右边限制的是p本身。
const放在*的右边的意思:表示指针变量p本身不可以修改了,但是指针指向的内容是可以通过指针变量来改变的。
如果想限制p,就放在的右边,如果想限制p所指向的内容,就放在的左边。
3 .comst放在*的两边:const int * const p
这个意思就是指针变量p不能被修改,指针变量p指向的内容也不能被修改。
1.3 总结:
- const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本身的内容可变。
- const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。
2、指针运算
指针的基本运算分为三类,分别是:
- 指针+-整数
- 指针-指针
- 指针的关系运算
2.1 指针+-整数
数组在内存中是连续存放的,因此,只要知道第⼀个元素的地址,顺藤摸瓜就能找到后面的所有元素。
当我们拿到首元素地址,我们可以将后面的都拿到吗?
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* p = &arr[0];//获得第一个元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);//求元素个数
for (int i = 0; i < sz; i++)
{
printf("%d ", *(p + i));//指针+整数
}
return 0;
}
打印结果:
当我们知道数组第一个元素的地址,就可以通过指针加减整数的方式得到其它的元素。
2.2 指针-指针
指针就是地址,所以指针减指针就是地址减地址,那指针减指针有什么用处呢?
指针-指针得到的是两个指针间的元素个数
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%d ", &arr[9]-&arr[0]);
return 0;
}
结果展示;
指针式分大小的,大的指针减小的指针得到的是正数,小的减大的是负数
总结:指针-指针的绝对值是两指针间的元素个数。
前提条件:两个指针指向同一块空间才能相减。也就是需要指向同一个数组才能相减。
2.3 指针的关系运算
在前面介绍数组的时候,有说过一个知识点:数组随着下标的增长,地址是由低到高变化的
比如说我们想打印下面这个数组中的元素
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
while (p < &arr[sz])//p是起始地址,随着下标增长,地址也会变高,因此起始地址肯定低于后面的地址
{
printf("%d ", *p);
p++;
}
return 0;
}
通过大小关系我们可以打印出该数组的所以元素。
3、指针的使用
指针是一种用于存储变量地址的特殊变量,通过它可以间接访问和操作所指向的内存空间中的数据。
通过前面的学习我们也了解了指针的一些相关知识,那么指针的使用包含哪几个方面呢?
1.声明指针:使用特定的类型声明指针变量,比如 int * p
;
表示声明一个指向整数的指针。
2.赋值:可以将变量的地址赋值给指针,比如 *p = &n;表示将n的地址赋给p,从而改变指针p所指向的值。
3.解引用:通过解引用指针可以访问指针所指向的变量,例如*p = 100
;
表示将指针所指向的整数赋值为100.
4.指针运算:可以对指针进行加减运算,以移动指针指向不同的内存位置。
结语:
本篇文章主要介绍了一个关键字const修饰变量的作用,以及指针的运算和指针的使用。关于指针的传址调用的介绍,在函数篇那里就已经介绍的比较完善了,如果有想了解了可以看一看。
C语言函数:编程世界的魔法钥匙(1)-学习笔记-CSDN博客
下期再见!!!
版权归原作者 JonlyMay 所有, 如有侵权,请联系我们删除。