指针基础知识
一、指针简介
指针是一个特殊的变量,是C语言里面一个变量(特殊的变量),也用于保存具体值,特殊之处在于指针用于保存内存中的地址,(内存地址是什么?内存是计算机中的存储部件,每个储存单元游固定唯一的编号,这里的编号就是内存地址)
二、获取地址
1、C语言中通过 & 操作符获取程序元素的地址
2、&可获取变量、数组、函数的起始地址
3、内存地址的本质是一个无符号整数(4字节或8字节)
三、指针定义的语法
指针定义语法:type*pointer
1、type—数据类型,决定访问内存时的长度范围
2、*—标志,意味着定义一个指针变量
3、pointer—变量名,遵循C语言命名规则
四、指针内存访问:*pointer
1、 指针访问操作符(*)作用于指针变量即可访问内存数据
2、指针的类型决定通过地址访问内存时的长度范围
3、指针的类型统一占用4字节或8字节
即:sizeof(type*)==4或8
例子显示(NULL专用的指针零值):
深入理解指针与地址
一、初学指针的军规
1、type*类型的指针只保存type类型变量的地址
2、禁止不同类型的指针相互赋值
3、禁止将普通数值当作地址赋值给指针(指针保存的是有效地址)
二、通过指针实现两个值的交换
问题:怎么编写函数交换两个数的值(在函数内修改函数外的变量)
初学中我们常常使用这样的想法来改变一个变量的值:但是这样是错误的
但是通过指针可以实现在函数内修改函数外的变量:
因此可以通过指针访问地址直接改变两个变量的值
指针与数组
一、数组的一些事实
1、数组的本质的是一片连续的内存
2、数组的地址是什么?(数组的起始地址&a)
3、如何获取?(使用&操作符获取)
4、数组名可以看作一个指针,代表数组中0元素的地址 (a<=>&a[0])!!
二、指针指向数组时,可进行的指针运算
显然&a与a数值上是相等的,但是意义上完全不一样
1、&a代表数组地址,类型为:int*[5]
2、a代表的数组0号元素的地址,类型为int*
证明:
int a[]={1,2,3,4,5,};
int p = a;//指向a数组的0号元素,则a = p
a[i]<=>(a+i)<=>(p+i)<=>p[i]
注意:int类型+int类型=>int*类型
三、字符串拾遗
1、C语言中的字符串常量是char类型,一种指针类型
这里“D.T.Software”是全局数据区,是char类型指针!
四、指针移动“组合拳” :int v=*p++
解读:指针访问操作符(*)和自增运算操作符(++)优先级相同
所以等价于:
int v = *p;
p++;
注意:数组名不能直接用来打“组合拳”
错误示例:
int a[]={1,2,3};
int v = *a++;//此处进行了a=a+1是错误的,不能更改a的数值!!
再论数组成为参数:
实际没有数组参数一说,最终数组形参会退化为指针,因此,不包含数组实参的长度信息,使用数组名调用时,传递的是0号元素的地址!
然后调用上面函数:(编译通过了,说明数组作为参数退化称为了指针)
*//int v = a++;的是编译错误的
说明了a[]参数退化成为了一个指针,一个与数组a0号元素地址相等的指针;
代码示例:
这里用*访问了“D.T.Software”,“D.T.Software”是一个指针,所以第一个打印的是第一个元素的值‘D’。后面连续判断,直到最后/0时,结束打印,最终打印出完整的“D.T.Software”!
指针与函数
一、函数的一些本质的事实
1、函数的本质是一段连续的代码(占用一片连续内存)
2、函数拥有返回类型和参数类型列表
3、函数名就是函数代码的起始地址(函数入口地址)
4、通过函数名调用函数,本质为指定具体地址的跳转执行
因此,可以定义指针,保存函数入口地址
例子:函数指针( Type func(Type1 a,Type1 b) ),与数组相似,函数名func就是函数入口地址,类型为Type(*)(Type1,Type2),与数组不同的是,函数中&func与func数值相同,意义也相同!
通过上述介绍,可以这样使用(定义指针,保存函数入口地址):
这里
pFunc = add;等价于pFunc = &add;相同地,pFunc = mul;也等价于pFunc = &mul;
pFunc(x,y)等价于(*pFunc)(x,y),编写代码时可以选择自己用的习惯的写法!
二、函数成为指针参数(定义指针函数,使用相同代码实现不同功能)
当使用calculate(a, 5,add);时就相当执行了1+…+5的操作。相同地,calculate(a, 5,mul);时就执行了1*…*5的操作。
三、注意事项
1、函数指针只是单纯的保存函数入口地址,只能调动函数,不能进行指针移动。
指针与堆空间
一、内存空间区域
1、全局数据区:存放全局变量,静态变量
2、栈空间:存放函数参数,局部变量
3、堆空间:用于动态创建变量(数组)
堆空间本质:备用的”仓库“,程序可在需要时从”仓库“申请使用内存(动态还)。当不需要使用时,需要立刻归还(动态还)
二、预备知识—void*
1、void类型(无长度信息)是基础类型,对用的指针类型是void*(无法获取内存中的数据)void类型可以保存任意类型的地址!但是无法用访问里面的数据!
显示错误:无法用*访问void里面的数据!
注意:void*类型的指针可以合法的直接赋值给其他具体数据类型的指针变量,可以和其他类型指针相互赋值