C语言指针、地址和数组函数堆空间的关系是什么


这篇“C语言指针、地址和数组函数堆空间的关系是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言指针、地址和数组函数堆空间的关系是什么”文章吧。指针是C语言中的变量因为是变量,所以用于保存具体值特殊之处,指针保存的值是内存中的地址内存地址是什么?内存是计算机中的存储部件,每个存储单元有固定唯一的编号内存中存储单元的编号即内存地址需要弄清楚的事实程序中的一切元素都存在于内存中,因此,可通过内存地址访问程序元素。内存示例获取地址C语言中通过 & 操作符获取程序元素的地址& 可获取变量,数组,函数的起始地址内存地址的本质是一个无符号整数(4字节或8字节)下面看一个简单的例子:下面为输出结果:注意事项只有通过 内存地址+长度 才能确定一个变量中保存的值。指针定义语法:type *point;type – 数据类型,决定访问内存时的长度范围* 标志,意味着定义一个指针变量pointer 变量名,遵循C语言命名规则例如:指针内存访问:* pointer指针访问操作符(*)作用于指针变量即可访问内存数据指针的类型决定通过地址访问内存时的长度范围指针的类型统一占用 4 字节或 8 字节即:sizeof(type*) == 4或 sizeof(type*) == 8下面看一段代码,感受一下:下面为输出结果:注意 NULL 地址为 00000000小结指针是C语言中的变量(本质为容器)指针专用于保存程序元素的内存地址可使用 * 操作符通过指针访问程序元素本身指针也有类型,指针类型由 数据类型+* 构成灵魂三问指针类型和普通类型之间的关系是什么?何看待“内存地址+长度才能访问内存中的数据”?不同类型的指针可以相互赋值吗?初学指针的军规Type* 类型的指针只保存 Type 类型变量的地址禁止不同类型的指针相互赋值禁止将普通数值当作地址赋值给指针注意:指针保存的地址必须是有效地址下面看一段代码:下面为输出结果:这个程序犯了两个错误:1、将不同类型的指针相互赋值,虽然 int 类型的指针变量保存的地址是对的,但是其所保存的值是错的。2、 将普通数值当作地址赋值给指针,这会导致严重的错误,不能正确输出编写函数交换两个变量的值想要编写函数交换变量的值,那么,必须有能力在函数内部修改函数外部的变量!!!看下面的代码:下面为输出结果:小结论可以利用指针从函数中“返回”多个值 (return只能返回一个值)!!下面看一段代码:下面为输出结果:这段代码中的子函数通过指针,计算了1加到5以及1乘到5的值,这就间接地通过指针从子函数“返回”多个值小结指针是变量,因此赋值时必须保证类型相同指针变量保存的地址必须是有效地址通过指针参数一能够实现函数交换变量的值一能够从函数中“返回”多个值问题数组的本质是一片连续的内存,那么,数组的地址是什么?如何获取?一些事实使用取地址操作符&获取数组的地址数组名可看作一个指针,代表数组中 0 元素的地址当指针指向数组元素时,可进行指针运算(指针移动)深入理解数组地址( int a[]= {1, 2, 3, 4, 5}; )&a 与 a 在数值上相同,但是意义上不同&a 代表数组地址,类型为:int(*)[5]a 代表数组0号元素地址,类型为: int*指向数组的指针: int (*pName)[5] = &a;下面看一段代码:下面为运行结果:需要注意的是,p 和 pa不是一个指针类型,所以令 p = pa 这种做法是不正确的。注意数组名并不是指针,只是代表了0号元素的地址,因此可以当作指针使用。指针与数组的等价用法假如:int a[ ] = {1, 2,3, 4,5}int* p = a;则以下等价:a[i] *(a + i) *(p + i) p[i]下面看一段代码,加深理解:下面为输出结果:这里可以看到 a和 p的地址不同,因为它们是两个不同的指针变量。字符串拾遗字符串常量是 char* 类型,一种指针类型指针移动组合拳:int v = *p++;解读:指针访问操作符(*)和自增运算操作符(++) 优先级相同所以,先从p指向的内存中取值,然后p进行移动等价于:int v = *p;p++;下面看一段代码,体会一下:下面为输出结果:因为D.T.Software 在全局数据区的起始地址一样,所以两次打印出来的地址一样。小结数组名可看作一个指针,代表数组中0元素的地址&a与a在数值上相同,但是意义上不同C语言中的字符串常量的类型是 char *当指针指向数组元素时,才能进行指针运算问题函数调用时会跳转到函数体对应的代码处执行,那么,如何知道函数体代码的具体位置?深入函数之旅函数的本质是一段内存中的代码(占用一片连续内存)函数拥有类型,函数类型由返回类型和参数类型列表组成例:函数的一些事实函数名就是函数体代码的起始地址(函数入口地址)通过函数名调用函数,本质为指定具体地址的跳转执行因此,可定义指针,保存函数入口地址函数指针( Type func (Type1 a,Type2 b))函数名即函数入口地址,类型为 Type(*)(Type1,Type2)对于 func 的函数,&func 与 func 数值相同,意义相同指向函数的指针:Type (*pFunc) (Type1, Type2) = func;函数指针参数函数指针的本质还是指针(变量,保存内存地址)可定义函数指针参数,使用相同代码实现不同功能注意函数指针只是单纯的保存函数的入口地址因此只能通过函数指针调用目标函数不能进行指针移动(指针运算)下面看一段代码,理解一下:下面为输出结果:这里注意,只有调用的时候,才能确定 calculate() 子函数中的 cal 是什么函数。再论数组参数函数的数组形参退化为指针!因此,不包含数组实参的长度信息。使用数组名调用时,传递的是0号元素的地址。void func(int a[ ]) vo免费云主机域名id func(int* a) void func (int a[1]) void func (int a[10) void func(int a[100)下面看一段代码:下面为输出结果:定义的形参arr[]可以进行 *arr++ 的操作,这就说明函数的数组形参退化为指针,因为数组不可以进行 ++ 的运算。小结函数名的本质是函数体的入口地址函数类型由返回类型和参数类型列表组成可定义指向函数的指针:Type (*pFunc) (Type1,Type2);函数指针只是单纯的保存函数的入口地址(不能进行指针运算)再论内存空间内存区域不同,用途不同全局数据区:存放全局变量,静态变量栈空间:存放函数参数,局部变量堆空间:用于动态创建变量(数组)堆空间的本质备用的“内存仓库”,以字节为单位预留的可用内存程序可在需要时从“仓库”中申请使用内存(动态借)当不需要再使用申请的内存时,需要及时归还(动态还)问题如何从堆空间申请内存?如何归还?预备知识– void*void 类型是基础类型,对应的指针类型为 void*void* 是指针类型,其指针变量能够保存地址通过 void* 指针无法获取内存中的数据(无长度信息)void* 总结不可使用void*指针直接获取内存数据。void*指针可与其它数据指针相互赋值。下面看一段代码:下面为输出结果:注意几个问题:1.void* 指针可以保存任意类型的地址2.void* 类型的指针无法访问内存中的数据3.void* 类型的变量可以直接合法的赋值给其他具体数据类型的指针变量4.void* 是例外,其他指针类型的变量不能相互赋值堆空间的使用工具箱:stdlib.h申请:void* malloc ( unsigned bytes )归还:void free( void* p)堆空间的使用原则有借有还,再借不难(杜绝只申请,不归还)malloc申请内存后,应该判断是否申请成功free只能释放申请到的内存,且不可多次释放(free 释放的是堆空间的地址)下面看一段代码感受一下:下面为输出结果:小结堆空间是程序中预留且可用的内存区域void*指针只能能够保存地址,但无法获取内存数据void*指针可与其它数据指针相互赋值malloc申请内存后,应该判断是否申请成功free只能释放申请到的内存,且不可多次释放多级指针可以定义指针的指针保存其它指针变量的地址如:Type v;
Type *pv = &v;
Type** ppv = &pv;
type*** pppv = &ppv;下面看一段代码:下面为输出结果:*pp 就是取 pp 里面的内容,而 pp 里面存的内容是 p 的地址,所以 *pp 就相当于p 的内容,而 p 的内容就是 a 的地址,所以说 **p 就相当于 a,**p = 2 也就是把 2 赋值给 a,*pp = &b 即为 p = &b,所以 *p = 3,就是把 3 赋值给 b。下面再看一段代码:下面为输出结果:这里特别注意:函数外的一个一级指针指向了这里申请的堆空间再论二维数组二维数组的本质是一维数组 ,即:数组中的元素是一维数组!!因此:int a[2][2];a 就是 &a[0]a[0] 的类型是 int[2]可知 a 的类型是 int (*)[2]下面看一段代码:下面为输出结果:pnb[0]是[1,2],pnb[1]经过赋值后是[30,4],所以*(pnb[1])就是取该数组所代表的第0个元素,也就是30。下面再看一个代码:这段代码是有问题的, func() 函数执行后, var 这个变量就会被销毁,所以 p 指向了一个不合法的地址。以上就是关于“C语言指针、地址和数组函数堆空间的关系是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注百云主机行业资讯频道。

相关推荐: 怎么把Oracle数据库从RAC集群迁移到单机环境

这篇文章主要介绍了怎么把Oracle数据库从RAC集群迁移到单机环境的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,免费云主机域名相信大家阅读完这篇怎么把Oracle数据库从RAC集群迁移到单机环境文章都会有所收获,下面我们一起来看看吧。1、源数据库…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 04/23 15:15
Next 04/23 15:16

相关推荐