指针极简教程

指针

指针的定义

指针即地址

0x3d4f0x3d500x3d510x3d52
56734895

上表是一个关于地址存储空间的举例,每个地址均对应一个存储空间,或者说,计算机中每一个存储空间都有编号,用以表明位置,称为指针。

通常我们所声明的变量,都是储存在一个或多个地址拼合在一起的一块存储空间中。

指针,存放的是一个地址值,不同类型的变量有不同类型的地址值。

声明整型指针变量

野指针

int *p ;

这样一句代码 , 就声明了一个int型的指针变量p,由于没有初始化,p此时称为一个野指针,对野指针的操作是非常危险的。

空指针

int *p = NULL;

通过这一语句,可以声明一个指向NULL的指针变量p,由于它指向的是NULL,可以认为它不指向任何地址,称为空指针(实际上一般认为指向内存地址0位,由于此地址需要极高权限操作,所以空指针一般是安全的。

取地址符

int a = 3;
int *p = &a;

通过这样一部分代码,我们定义了一个有初值的int型指针变量p,它的初值是int型变量a的地址,& 符号就是取地址符,可以获得一个变量的地址。

在p指向变量a的地址后,便可以通过(*p)取得变量p所指向的变量的值,也就是变量a的值,同时对(*p)的任何操作也会直接影响变量a。

联系C语言中的整型基本读入语句,scanf("%d",&a);这即是把从控制台窗口读入的值,写入了变量a的地址中,再加上上方的语句,此时变量p的值就是变量a的地址,所以这句语句也可以这样表达scanf("%d",p);

指针的作用

指针最常见的作用就是在参数中传递变量的地址,举例如下

传值与传地址

传值

void Swap(int a, int b){
    int temp = a;
    a = b;
    b = temp;
    return;
}


int main(){
    int x = 5 , y = 7;
    Swap(x,y);
    cout<<x<<'\t'<<y<<endl;
}

函数的功能显然是想要交换形参a与b的值,但这是无法做到的,因为函数的形参变量是传值的,即当前的Swap函数相当于只是获得了来自调用处函数的两个整型值(5和7),并在Swap函数内新声明了变量a和b保存这两个整型值,而不是获得了两个变量(x和y)。

传地址

void Swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
    return;
}


int main(){
    int x = 5 , y = 7;
    Swap(&x,&y);
    cout<<x<<'\t'<<y<<endl;
}

以上的程序片段是可以完成交换功能的,函数的参数并不是两个整型变量,而是两个整型指针变量,传入的是两个变量x,y的地址,(*a)与(*b)是直接对变量x,y的地址所存储内容的修改

举个可能不太恰当的例子,现在有两个瓶子,一个装的是橙汁,一个装的是可乐,需要人来交换他们的内容,上面传值的函数是找来的人又弄来了两个瓶子,里面有一瓶完全一样的橙汁和一瓶完全一样的可乐,并且用第三个瓶子(temp)把他们交换了,而需要交换的两个瓶子并没有发生任何变化。

但下面传地址的函数找来的人直接找到了这两个瓶子的位置,又拿了一个瓶子(temp)过来,交换了他们的内容,这次,这两个瓶子里的内容成功交换了。

尝试

根据Swap函数,构造一个函数,能够求出传入的两个参数的和,并保存在第一个参数中带回主调函数中

更多的指针

其他类型变量的指针

之前介绍的都是int *型的指针,而C/C++有众多的类型,显然我们知道指针不止此一种,一般某种类型的变量,我们只使用此类型的指针保存它的地址,反例如下

float a = 3.1415926535;
int *p = a;

此程序段编译时就会报错,如果通过强制类型转换,把代码改为

float a = 3.1415926535;
int *p = (int *)&a;

编译便不会报错,但是由于这只是简单的把变量a的地址强制转换成了(int *)类型,地址所存储的二进制码并没有变,所以*p此时的值并不是3,而是1078530011,这其中有一些不可告人的处理转换,详情可以学习整型编码与浮点数编码

数组的指针

当我们在C/C++内声明一个数组,也就是内存中占用了一段连续的地址,长度为每个单元的长度*数组长度,继续举例

int arry[100];
int *p = arry;

由上面的程序可以发现,声明的数组名也就是这一段内存的首地址,*p即可访问arry[0],由于上面说明数组的地址是连续的,所以可想而知
*(p+1)即可访问arry[1],(这里的括号不可缺少,由于*的优先级高于加法运算符+,所以需要加上括号,否则相当于(*a)+1这样的一个表达式

注意 对于不同的指针类型,+1操作所跳过的地址值不同,如对于(int )型指针 int ptr; ptr+1将指向ptr所对应的地址后第四个位置,即增加了一个int的长度,指向了数组中或内存中下一个int型变量的地址,(由于此操作不管下面四个字节是否保存的是int,都会当做int取出,所以尽量减少对内存位置区域的改变

指针的数组

与普通数组几乎同理,只是存放的内容是地址

int a , b;
int * p[10];
p[0] = &a;
p[1] = &b;

指针的指针

既然指针变量本身也是一个变量,那么便可以用一个指针指向它,

int a;
int *x = &a;
int **y = &x;

int * p[10];
int ** q = p;

如上例,x是一个指向变量a的指针,y是一个指向int型指针的指针

而下面的两个语句,由于在上面数组的指针中提到,数组名本身就是一个指向内存中数组所在位置的首地址,所以数组名本身就是一个指针,那么指针数组的数组名也就是一个指针的指针,所以不需要取地址符便可以直接赋值给一个 指针的指针变量 q

另外,关于取地址符的反向操作,对一个地址取内容的操作符 *,是根据所给地址值,返回地址处的数据,由于指针的指针是层层指向的,所以对于这样的情况,取出地址中的值也要层层取出,对于上面的程序片段

int * p[10];
int ** q = p;

使用 *q可以取出q所指向变量地址处的内容,而q指向一个(int *)的指针,所以得到的还是一个指针(p[0]),再做一个运算才能得到一个int型变量,即**q

尝试

一维数组

声明一个一维数组,使用刚刚的方法,用一个指针保存数组的首地址,并用此指针存取数组中的元素

多维数组

声明一个多维数组,试着使用指针来存取多维数组的元素

多维指针数组

太复杂了,写出这种的都该判刑!

申请内存空间

调用malloc或new会返回一段在内存中申请的空间的地址,所以需要用一个指针接收

free对应 malloc申请的空间 ,delete对应 new申请的空间 , 不可以混用

free 或 delete 后 , 要记得把接收地址的指针变量值置为NULL

C语言 :malloc() ,free()

C++:new , delete

扩展应用

链表

用基本的struct构建一个C语言风格的链表,实现链表的创建,删除,插入节点,搜索,[倒置],(排序)

struct Node{
    int data;
    Node* next;
};

树(二叉树)

根据二叉树的基本节点,创建一颗具备最基本的二叉树,附加递归等知识,实现二叉树的构建,删除,查找,三序遍历,叶节点计数

struct Node{
    int data;
    Node* leftson;
    Node* rightson;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值