我是靠谱客的博主 朴素滑板,这篇文章主要介绍C语言基础之指针一、地址概念的引入二、通过指针来访问变量三、指针分类型&指针和数组四、数组指针函数的结合五、为什么要用指针?六、指针数组七、数组指针八、函数指针九、无类型的指针&&malloc十、什么是内存泄漏,如何避免十一、指针收官,现在分享给大家,希望可以做个参考。

指针篇

  • 一、地址概念的引入
  • 二、通过指针来访问变量
  • 三、指针分类型&指针和数组
  • 四、数组指针函数的结合
  • 五、为什么要用指针?
  • 六、指针数组
  • 七、数组指针
  • 八、函数指针
  • 九、无类型的指针&&malloc
  • 十、什么是内存泄漏,如何避免
  • 十一、指针收官

一、地址概念的引入

1.看代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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.比如看代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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.检测指针的偏移值

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#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.注意:注意指针偏移的位置,不要超出了数组的范围,因为数组的元素数据地址是连续的,超出了就会出现乱码,因为访问不到

四、数组指针函数的结合

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#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.用指针让某个地址强制转换成我们需要的值

复制代码
1
2
3
4
5
6
7
8
9
#include<stdio.h> int main(){ int *p = (int *)0x0060ff00; *p = 10; printf("在内存的%p的位置,存放的值是:%dn",p,*p); //结果是:在内存的0x0060ff00的位置,存放的值是:10 return 0; }

2.来看两段代码
第一段

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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,没有改变,从某种意义上说,这样调用函数毫无意义

第二段

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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.顾名思义就是指针的数组,好多个指针放在一起,是一个数组,每一个元素都是指针

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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.顾名思义就是数组的指针,一个指针,这个指针存放的是数组的地址

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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.函数的指针,还是一个指针变量,它存放的是函数的地址
看代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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开辟出来的数据空间与数组的结合

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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语言基础之指针一、地址概念内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部