不同类型的指针变量是可以直接相互赋值的_C语言指针——入门指南

Hello      大家好

欢迎关注编程猎人

本人小白一枚

一个立志成为分享编程干货的博主efacc8c964076e451e25145f09b67dc7.png

5e014bffccafc32bf87ae7d5f5c9618c.png

一,什么是指针?

二,指针的注意事项?

三,指针与数组

四,指针与函数

五,指针与堆空间

一,什么是指针?

C语言中变量是容器,可看作装酒的酒杯,只不过装的不是酒,是各种内存。

而指针是一种特殊的变量:因为是变量,所以能保存具体值;特殊之处就在于指针保存的值是内存的地址;

内存地址:计算机中每个存储单元都有编号,这些编号就是内存地址。

需要清楚的事实:程序中一切元素都存储在内存中,因此可以通过访问地址来使用元素,而指针的作用就是作为一个容器存储地址,对地址的一切操作都要通过指针来完成。

如何获取具体地址:

通过取地址操作符——& 来获得。

&的作用:可以获取变量,数组,函数的地址。

确定一个具体的地址是通过:确定起始地址+长度来确定。

各种数据类型长度:

7dbed35bb2fb693a9015797a33af5af1.png

指针定义语法:type* pointer;

type 数据类型,决定访问内存的长度;

注意:指针的类型统一只占4字节或8字节。

* 指针访问操作符,标志为指针变量。

pointer 变量名,遵循C语言命名规则。

int main(){    char* pChar;    int* pInt;    double* pDouble;        return 0;}
int var=0 ;            //定义变量var初始值为0;int* pvar=NULL ;       //定义pvar的所占地址的开始值为NULL,即0值;pvar = &var;           //把var变量的地址赋值给pvar.*pvar = var;           //把var的值赋值给*pvar.

归类:var,*pvar为int类型变量;

           pvar,&var为变量地址;

二,指针的注意事项

type* 类型的指针只能存储type类型变量的地址;

禁止不同类型的指针相互赋值;

通过指针参数:

——能够实现函数交换变量的值;

——能够从函数中"返回"多个值;而return只能返回一个值;

三,指针与数组

在数组中,元素本身就是地址。所以数组名虽然不是指针,但可以看作指针;

这样的话,数组元素就可以直接对指针赋值,数组名也可以对指针赋值。

数组名可直接看作一个指针,表示数组中0元素的地址;

a等价于&a[0]

不过&a则表示整个数组的地址,虽然值和0元素的地址一样,但意义不同。

85fa9e0bdfce332f82208ad0a0046047.png

——&a代表数组地址,类型为:int(*)[ ] 

——a代表数组0号元素地址,类型为:int*

看得出两者类型不一致,所以不能相互赋值。

所以定义:

指向数组的指针:int (*pName)[ ] = &a;

指向数组0号元素的指针:int* pName = a; 

当指针指向数组元素时,可以进行指针移动。

int a[] = {1, 2, 3, 4, 5};int* pa = a;p = p + 1;             //现在p指向了下一个元素。

指针与字符串:

字符串其实就是特殊的数组,特殊在于该数组最后元素的值为'\0'。

字符串常量就是一种char*类型,一种指针类型,存在的地址为全局变量区。

使用字符串的时候,其实就是在使用char*类型的数据。

例如用&对"Hello"取地址,结果为"Hello"在全局变量区的起始地址。

"Hello"可看作一个地址;

*"Hello"看作从这个地址中取值;

四,指针与函数

函数的本质就是内存中的一段代码:

d039853365ab612983489972c5e0a8dd.png

函数的类型,函数类型由返回类型和参数类型列表决定:

4700296a3704e89515d9e090c75880de.png

函数名就是函数体代码的起始地址;

通过函数名调用函数,本质为指定具体地址的跳转执行

因此,可以通过指针,保存函数入口地址;

函数指针:

对于函数为type func (type 1,  type 2)格式的

指向该函数的指针为:type (*pfunc)(type 1,  type 2) = func/NULL;

值得注意的是,函数指针只是单纯的保存函数的入口地址,所以只能通过函数指针调用目标函数。

当数组作为参数时:

当数组作为参数,会退化成为一个指针;

int demo(int arr[ ],int len) → int demo(int* arr, int len).

因此,不包含数组实参的长度信息。使用数组名调用时,传递的是0号元素的地址。

五,指针与堆空间

各类内存空间不同,用途不同:

——全局数据区:存放全局变量,静态变量;

——栈空间:存放函数参数,局部变量;

——堆空间:用于动态创建变量

堆空间的本质:

  • 备用的“内存仓库”,以字节为单位预留可用内存。

  • 程序可在需要时申请借内存。(动态借)

  • 借完后需要及时归还。(动态还)

问:如何从对卡申请借内存,如何归还呢?

预备知识——void*

  1. void类型时基础类型,对应指针类型为void*

  2. void*为指针类型,其指针变量能够保存地址

  3. 通过void*指针无法获取内存中的数据(无长度信息)

  4. void*保存的内存有起始地址,但没有长度信息。能够保存任意类型的地址,能转换到其它指针类型的变量。

  5. 不可以用void*指针直接获取内存数据,不过void*与其它数据指针可以相互赋值。

堆空间的使用原则:

  1. 有借有还。

  2. malloc申请内存后,应该判断是否申请成功。

    =NULL,则申请不成功。
    !=NULL,则申请成功。
  3. free负责释放申请到的内存。

今天的分享到这里就结束了,不知道大家有没有学废呢?学废的朋友可以把“学废了”敲在留言上,或者和笔者讨论哦。

da572bcc3838842cc3cdc1f8002d4e01.png

这是笔者的微信公众号,欢迎关注!


版权声明:本文为weixin_28716723原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。