概述
指针篇
- 一、地址概念的引入
- 二、通过指针来访问变量
- 三、指针分类型&指针和数组
- 四、数组指针函数的结合
- 五、为什么要用指针?
- 六、指针数组
- 七、数组指针
- 八、函数指针
- 九、无类型的指针&&malloc
- 十、什么是内存泄漏,如何避免
- 十一、指针收官
一、地址概念的引入
1.看代码
#include<stdio.h>
int main()
{
int juHuatai = 10;
int meiGuiTai = 9;
printf("变量名获取ju=%dn",juHuaTai);
printf("变量名获取mei=%dn",meiGuiTai);
printf("ju的地址是:%pn",&juHuaTai);
printf("mei的地址是:%pn",&meiGuiTai);
printf("通过地址来获取ju=%dn",*(&juHuaTai));
printf("通过地址来获取:%dn",*(&meiGuiTai));
return 0;
}
2.看运行结果
3.所以
1)变量的访问方式有两种:变量名和地址
2) & 取地址,取变量名所代表的变量的地址
3) 这里的 * 代表的是一个运算符,跟 ±*/ 类似,该运算符的作用是:取出地址内存中数据的值(取内容)
4) 指针 = 地址!!!
二、通过指针来访问变量
1.什么是指针变量?
-
指针变量是存放指针的变量
-
指针变量是存放地址的变量
2.比如看代码
#include<stdio.h>
int main()
{
int a;
a = 10;
char c;
c = 'h';
int *p;//定义了一个整型数指针 p
p = &a;//初始化指针 p = a的地址
char *lp;//定义了一个字符型指针 lp
lp = &c;//初始化指针 lp = c的地址
printf("a = %dn",a);
printf("c = %cn",c);
printf("p = %dn",*p);
printf("lp = %cn",*lp);
return 0;
}
3.看运行结果
4.所以
a.整形变量存放的是整数
b.字符变量存放的是字符
c.指针变量存放的是地址
注意: 指针只有在定义一个指针变量的时候,才算是指针的标识符,其他情况,都是一种运算符,表示取内容
三、指针分类型&指针和数组
1.检测指针的偏移值
#include<stdio.h>
int main()
{
int *p;
char *p2;
int a = 10;
char c = 'A';
p = &a;
p2 = &c;
//指针++
printf("a的地址为:%pn",p);
printf("a的地址++后为:%pn",++p);
printf("c的地址为:%pn",p2);
printf("c的地址++后为:%pn",++p2);
int array[3] = {1,2,3};
int *parray;
parray = array;
printf("第一个元素的地址是:%pn",parray++);
printf("第二个元素的地址是:%pn",parray++);
printf("第三个元素的地址是:%pn",parray);
//注意:此时数组的地址已经移到最后面了,如果使用要重新把地址移向数组的首地址
parray = array;//也可以 parray = array[0];
int i;
for(i=0;i<3;i++){
printf("数组的第%d个元素是:%dn",i+1,*parray++);//也可以用数组的下标来访问 array[i]
}
return 0;
}
2.看运行结果
3.所以
1.指针分类型
2.指针++根据类型不同,偏移值也不同
3.指针和数组关心的是数组的首地址,数组的第一个元素的地址,也可以是数组名
4.注意:注意指针偏移的位置,不要超出了数组的范围,因为数组的元素数据地址是连续的,超出了就会出现乱码,因为访问不到
四、数组指针函数的结合
#include<stdio.h>
#include<stdlib.h>
//提示用户输入10个成绩,找最高分,找最低分,算出平均分
void initScores(int *datas,int size)
{
int i;
for(i=0;i<size;i++){
printf("请输入第%d个分数:n",i+1);
scanf("%d",datas);
if(*datas > 100 || *datas < 0){
printf("请输入0-100的分数成绩!n");
exit(-1);
}
datas++;
}
}
void printScores(int *datas,int size)
{
int i;
for(i=0;i<size;i++){
printf("你输入的第%d个成绩是:%dn",i+1,*datas);
datas++;
}
}
int getMax(int *datas,int size)
{
int i;
int max;
max = *datas;
for(i=0;i<size;i++){
if(max < *datas){
max = *datas;
}
datas++;
}
return max;
}
int getMin(int *datas,int size)
{
int i;
int min;
min = *datas;
for(i=0;i<size;i++){
if(min > *datas){
min = *datas;
}
datas++;
}
return min;
}
float getAverage(int *datas,int size)
{
int i;
float average;
int total = 0;
for(i=0;i<size;i++){
total += *datas;//total = total + datas[i];
datas++;
}
average = (float)total / size;
return average;
}
void printRet(int max,int min,float average)
{
printf("最高分是:%d 最低分是:%d 平均分是:%fn",max,min,average);
}
int main()
{
int scores[10];
int len;
int max;
int min;
float average;
len = sizeof(scores) / sizeof(scores[0]);
initScores(scores,len);//函数调用中,传参就是一个赋值的过程!实际参数的值给形式参数
printScores(scores,len);
max = getMax(scores,len);
min = getMin(scores,len);
average = getAverage(scores,len);
printRet(max,min,average);
return 0;
}
五、为什么要用指针?
1.用指针让某个地址强制转换成我们需要的值
#include<stdio.h>
int main(){
int *p = (int *)0x0060ff00;
*p = 10;
printf("在内存的%p的位置,存放的值是:%dn",p,*p);
//结果是:在内存的0x0060ff00的位置,存放的值是:10
return 0;
}
2.来看两段代码
第一段
#include<stdio.h>
void jiajiaA(int p)
{
p = p + 1;
printf("调用函数中:a=%dn",p);
}
int main()
{
int a = 10;
jiajiaA(a);
printf("主函数的a=%dn",a);
return 0;
}
运行结果:
可以看到,主函数里面的a的值没有还是10,没有改变,从某种意义上说,这样调用函数毫无意义
第二段
#include<stdio.h>
void jiajiaA(int *p)//这里把a的地址传过来了,int *p = &a
{
*p = *p + 1;
printf("调用函数中:a=%dn",*p);
}
int main()
{
int a = 10;
jiajiaA(&a);
printf("主函数的a=%dn",a);
return 0;
}
看运行结果
可以看到,主函数里面的a的值也变成了11,前面学习函数说了函数传参是一个赋值的过程,调用函数中函数调用完就释放了数据内存,这里因为通过传递地址可以从根本上改变想要变量的值,而无关局部内存数据的释放,这也达到了它的意义
六、指针数组
1.顾名思义就是指针的数组,好多个指针放在一起,是一个数组,每一个元素都是指针
#include<stdio.h>
int main()
{
int a = 2;
int b = 3;
int c = 4;//三个毫无关系的整型变量
int array[3];//多个整数,叫做整数数组
//这么定义一个指针数组
int *parray[3];//多个指针,叫做指针数组,数组中的每一项元素都是一个指针变量
//指针变量是存放地址的变量
parray[0] = &a;
parray[1] = &b;
parray[2] = &c;//三个普通没有任何关系的整型变量的地址存入指针数组
int i;
for(i=0;i<3;i++){
printf(" %dn",*(parray[i]));//输出的结果无疑是:2 3 4
}
return 0;
}
七、数组指针
1.顾名思义就是数组的指针,一个指针,这个指针存放的是数组的地址
#include<stdio.h>
int main()
{
int array[3] = {1,2,3};
int (*p)[3];//这样定一个指针
p = array;
int *p2;
p2 = array;
printf("偏移前p的地址为:%pn",p);
printf("偏移前p2的地址为:%pn",p2);
printf("偏移后p的地址++为:%pn",++p);
printf("偏移后p2的地址++为:%pn",++p2);
}
2.看运行结果:
3.所以
数组的指针,强调的是类型,数组的个数,偏移值是偏移了整个数组的大小
八、函数指针
1.函数的指针,还是一个指针变量,它存放的是函数的地址
看代码
#include<stdio.h>
void print()
{
printf("欢迎你的到来!n");
}
int main()
{
//如何定义一个函数指针!
void (*p)(); //1.如何表示指针 * 2.如何知道是函数:() 3.函数指针是专用的,格式要求很强(参数类型,个数,返回值),就像数组指针一样
//2.如何给函数指针赋值
p = print;//函数名就是地址,就像数组一样,数组名就是地址
//3.如何通过函数指针调用函数
p();//直接通过指针名字+()
(*p)();//取内容 (*指针名字)()
return 0;
}
2.看运行结果:
九、无类型的指针&&malloc
- 原型是: void *malloc(size_t size); 不知道指向的空间是什么属性
- 通常用在没有做初始化的野指针上,为野指针从新定义类型和大小
1.下面的代码是,用无类型的指针malloc开辟出来的数据空间与数组的结合
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
printf("请输入数组元素总个数:n");
scanf("%d",&n);
int *array = (int *)malloc(n * sizeof(int));
if(array == NULL){
printf("开辟空间失败!n");
}
int i;
for(i=0;i<n;i++){
printf("请输入第%d个学生的成绩:n",i+1);
scanf("%d",&array[i]);
}
for(i=0;i<n;i++){
printf("你输入的第%d个学生的成绩是:%dn",i+1,array[i]);
}
return 0;
}
2.看运行结果:
十、什么是内存泄漏,如何避免
1)内存泄漏是指:程序刚跑起来很好,跑了几个小时,或者几天,几周,程序崩溃了
2)如何避免:a.首要怀疑对象就是循环中有没有,使用malloc函数不断的申请开辟空间 b.及时合理的释放,利用free(指针名); 指针名 = NULL;
十一、指针收官
1)定义一个整型变量? int a;
2)定义p为指向整形数据的指针变量? int *p;
3)定义整型数组a,他有五个元素? int array[5];
4)定义指针数组p,它有四个指向整型数据的指针元素构成? int *p[4];
5)p为指向包含4个元素的一维数组的指针变量? int (*p)[4];
6)f为返回整型函数值得函数? int f();
7)p为返回一个指针的函数,该指针指向整型数据? int *p();
8)p为指向函数的指针,该函数返回一个整型值? int (*p)();
9)p是一个指针变量,它指向一个指向整型数据的指针变量? int **p;
10)p是一个指针变量,其类型为void(空类型),不指向具体的对象? void *p;**
最后
以上就是朴素滑板为你收集整理的C语言基础之指针一、地址概念的引入二、通过指针来访问变量三、指针分类型&指针和数组四、数组指针函数的结合五、为什么要用指针?六、指针数组七、数组指针八、函数指针九、无类型的指针&&malloc十、什么是内存泄漏,如何避免十一、指针收官的全部内容,希望文章能够帮你解决C语言基础之指针一、地址概念的引入二、通过指针来访问变量三、指针分类型&指针和数组四、数组指针函数的结合五、为什么要用指针?六、指针数组七、数组指针八、函数指针九、无类型的指针&&malloc十、什么是内存泄漏,如何避免十一、指针收官所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复