c语言的指针就该这么学

简介: 相信大家学c的时候,其他都好,但是遇到指针就有点头大。的确指针学起来有点晦涩难懂,但是指针是c的灵魂,可以说没有指针的c语言就像没有心脏的人,所以指针非常重要。

相信大家学c的时候,其他都好,但是遇到指针就有点头大。的确指针学起来有点晦涩难懂,但是指针是c的灵魂,可以说没有指针的c语言就像没有心脏的人,所以指针非常重要。❤️‍🔥❤️‍🔥❤️‍🔥

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

题一        题二        题三        题四        题五        题六        题七        题八         题九


熟话说熟能生巧,我多多练习一些指针的相信我们对指针就有更深的理解

提示:sizeof(数组名)-数组名表示整个数组-计算是整个数组的大小,&数组名-数组名表示整个数组,取出的是整个数组的地址除此之外,所有的数组名都是首元素的地址

题一

1.     整形数组
2. int a[]={1,2,3,4};
3. printf("%d\n",sizeof(a));//16
4. printf("%d\n",sizeof(a+0));//8 
5. printf("%d\n",sizeof(*a));//4 
6. printf("%d\n",sizeof(a+1));//8 
7. printf("%d\n",sizeof(a[1]));//4
8. 
9. printf("%d\n",sizeof(&a));//8 
10. printf("%d\n",sizeof(*&a));//16 
11. printf("%d\n",sizeof(&a+1));//8 
12. printf("%d\n",sizeof(&a[0]));//8
13. printf("%d\n",sizeof(&a[0]+1));//8

1. printf("%d\n",sizeof(a))//16

因为sizeof(数组名)-数组名表示整个数组的-计算是整个数组的大小,所以16个字节

2.printf("%d\n",sizeof(a+0));//8

由于他不是单独的sizeof(数组名),所以数组名表示首元素地址,a+0是首元素的地址,sizeof(a+0)计算的是地址的大小,32位平台是4,64位平台是8

3.printf("%d\n",sizeof(*a));//4

这a仍然是首元素的地址,然后解引用得到是求a[0]这个数大小,所以为4个字节

4.printf("%d\n",sizeof(a+1));//8

这a仍然是首元素的地址,a+1是第二个元素a[1]的地址,sizeof(a+1)计算的是地址的大小,32位平台是4,64位平台是8

5.printf("%d\n",sizeof(a[1]));//4

这求的就是a[1]这个元素的大小,4个字节

6.printf("%d\n",sizeof(&a));//8

&a虽然是数组的地址,但也是地址的大小,sizeof(&a)计算的是一个地址的大小,32位平台是4,64位平台是8

7.printf("%d\n",sizeof(*&a));//16

&a虽然是数组的地址,*(&a)就是整个数组,sizeof(*&a)求的整个数组的大小,16个字节

8.printf("%d\n",sizeof(&a+1));//8

&a+1指的是数组后面空间的地址,32位平台是4,64位平台是8

9.printf("%d\n",sizeof(&a[0]));//8

&a[0]就是第一元素的地址,32位平台是4,64位平台是8

10.printf("%d\n",sizeof(&a[0]+1));//8

&a[0]就是第一元素的地址,&a[0]+1就是第二个元素a[1]的地址,32位平台是4,64位平台是8

题二

1. 字符数组
2. char arr[]={'a','b','c','d','e','f'};
3. printf("%d\n",sizeof(arr));//6
4. printf("%d\n",sizeof(arr+0));//8
5. printf("%d\n",sizeof(*arr));//1
6. printf("%d\n",sizeof(arr[1]));//1
7. printf("%d\n",sizeof(&arr));//8
8. printf("%d\n",sizeof(&arr+1));//8
9. printf("%d\n",sizeof(&arr[0]+1));//8
10. 
11. printf("%d\n",strlen(arr));//随机值
12. printf("%d\n",strlen(arr+0));//随机值
13. printf("%d\n",strlen(*arr));//错误
14. printf("%d\n",strlen(arr[1]));//错误
15. printf("%d\n",strlen(&arr));//随机值
16. printf("%d\n",strlen(&arr+1));//随机值
17. printf("%d\n",strlen(&arr[0]+1));//随机值

  1. printf("%d\n",sizeof(arr));//6

   这有6个字符,所以整个数组大小为6

  2. printf("%d\n",sizeof(arr+0));//8

  由于他不是单独的sizeof(数组名),所以数组名表示首元素地址,a+0是首元素的地址, sizeof(a+0)计算的是地址的大小,32位平台是4,64位平台是8

   3.printf("%d\n",sizeof(*arr));//1

  *arr就是第一个元素a[0],所以大小就是1

   4.printf("%d\n",sizeof(arr[1]));//1

  arr[1]就是第二个元素,所以大小就是1

   5.printf("%d\n",sizeof(&arr));//8

   &arr表示整个数组的地址,32位平台是4,64位平台是8

   6.printf("%d\n",sizeof(&arr+1));//8

  &arr表示整个数组的地址,&arr+1表示这个数组后面的地址,32位平台是4,64位平台是8

   7.printf("%d\n",sizeof(&arr[0]+1));//8

  &arr[0]表示第一个元素的地址,&arr[0]+1表示第二个元素的地址&arr[1],32位平台是4,64位平台是8

   8.printf("%d\n",strlen(arr));//随机值

  strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   9.printf("%d\n",strlen(arr+0));//随机值

  arr+0首元素的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   10.printf("%d\n",strlen(*arr));//错误

   *arr是第一个元素,strlen会理解到你这是ASCII码值里的97,不是一个合法的地址,所以会发生错误

   11.printf("%d\n",strlen(arr[1]));//错误

  arr[1]是第二个元素,strlen会理解到你这是ASCII码值里的98,不是一个合法的地址,所以会发生错误

   12.printf("%d\n",strlen(&arr));//随机值

  &arr整个数组的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   13.printf("%d\n",strlen(&arr+1));//随机值

  &arr+1整个数组后面的的地址,strlen()是求字符的长度,遇见'\0'停止,没有'\0',所以strlen()不知道什么时候停下

   14.printf("%d\n",strlen(&arr[0]+1));//随机值

  &arr[0]+1就是第二个元素的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

题三

1. 字符数组
2. char arr[]="abcdef";
3. printf("%d\n",sizeof(arr));//7
4. printf("%d\n",sizeof(arr+0));//8
5. printf("%d\n",sizeof(*arr));//1
6. printf("%d\n",sizeof(arr[1]));//1
7. printf("%d\n",sizeof(&arr));//8
8. printf("%d\n",sizeof(&arr+1));//8
9. printf("%d\n",sizeof(&arr[0]+1));//8
10. 
11. printf("%d\n",strlen(arr));//6
12. printf("%d\n",strlen(arr+0));//6
13. printf("%d\n",strlen(*arr));//错误
14. printf("%d\n",strlen(arr[1]));//错误
15. printf("%d\n",strlen(&arr));//6
16. printf("%d\n",strlen(&arr+1));//随机值
17. printf("%d\n",strlen(&arr[0]+1));//5

   1.printf("%d\n",sizeof(arr));//7

   arr为字符串,末尾会跟有'\0',sizeof(arr)计算的整个数的大小,所以为7    

   2.printf("%d\n",sizeof(arr+0));//8

   arr+0是第一个元素的地址,32位平台是4,64位平台是8

  3.printf("%d\n",sizeof(*arr));//1

   *arr是第一个元素,大小为1

   4.printf("%d\n",sizeof(arr[1]));//1

   arr[1]是第二个元素,大小为1

  5.printf("%d\n",sizeof(&arr));//8

   &arr整个数组的地址,32位平台是4,64位平台是8

   6.printf("%d\n",sizeof(&arr+1));//8

   &arr整个数组的地址,&arr+1是整个数组后面的地址,32位平台是4,64位平台是8

  7.printf("%d\n",sizeof(&arr[0]+1));//8

   &arr[0]+1是第二个元素的地址,32位平台是4,64位平台是8

   8.printf("%d\n",strlen(arr));//6

   arr表示整个元素的地址,strlen遇到'\0'就停止,不会把'\0'计算在内,所以大小为6

   9.printf("%d\n",strlen(arr+0));//6

   arr+0表示首元素的地址,strlen遇到'\0'就停止,不会把'\0'计算在内,所以大小为6

   10.printf("%d\n",strlen(*arr));//错误

   *arr是第一个元素,strlen会理解到你这是ASCII码值里的97,不是一个合法的地址,所以会发生错误

   11.printf("%d\n",strlen(arr[1]));//错误

    arr[1]是第二个元素的地址,strlen会理解到你这是ASCII码值里的98,不是一个合法的地址,所以会发生错误

   12.printf("%d\n",strlen(&arr));//6

   &arr表示整个数组的地址,strlen遇到'\0'就停止,不会把'\0'计算在内,所以大小为6

   13.printf("%d\n",strlen(&arr+1));//随机值

   &arr+1是整个数组后面的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   14.printf("%d\n",strlen(&arr[0]+1));//5

   &arr[0]+1是第二个元素元素的地址,从第二个元素到'\0',有5个元素,所以长度为5

题四

1. 字符数组
2. char* p="abcdef";
3. printf("%d\n",sizeof(p));//8 
4. printf("%d\n",sizeof(p+1));//8
5. printf("%d\n",sizeof(*p));//1
6. printf("%d\n",sizeof(p[0]));//1
7. printf("%d\n",sizeof(&p));//8
8. printf("%d\n",sizeof(&p+1));//8
9. printf("%d\n",sizeof(&p[0]+1));//8
10. 
11. printf("%d\n",strlen(p));//6
12. printf("%d\n",strlen(p+1));//5
13. printf("%d\n",strlen(*p));//错误
14. printf("%d\n",strlen(p[0]));//错误
15. printf("%d\n",strlen(&p));//随机值
16. printf("%d\n",strlen(&p+1));//随机值
17. printf("%d\n",strlen(&p[0]+1));//5

   1.printf("%d\n",sizeof(p));//8

    sizeof(p)求的是指针变量的大小,32位平台是4,64位平台是8

   2.printf("%d\n",sizeof(p+1));//8

   p+1第二个元素的地址,32位平台是4,64位平台是8

   3.printf("%d\n",sizeof(*p));//1

   *p就是第一个元素,它的大小为1

   4.printf("%d\n",sizeof(p[0]));//1

   p[0]就是第一个元素,它的大小为1    

   5.printf("%d\n",sizeof(&p));//8

   &p指针p的地址,32位平台是4,64位平台是8

   6.printf("%d\n",sizeof(&p+1));//8

   &p指针p的地址,&p+1还是内存里的地址,32位平台是4,64位平台是8

   7.printf("%d\n",sizeof(&p[0]+1));//8

   &p[0]+1第二个元素的地址,32位平台是4,64位平台是8

   8.printf("%d\n",strlen(p));//6

   p是首元素的地址,到'\0'停止,所以长度为6

   9.printf("%d\n",strlen(p+1));//5

   p+1是第二个元素的地址,到'\0'停止,所以长度为5

  10.printf("%d\n",strlen(*p));//错误

   *p是第一个元素,strlen会理解到你这是ASCII码值里的97,不是一个合法的地址,所以会发生错误

  11.printf("%d\n",strlen(p[0]));//错误

   p[0]是第一个元素,strlen会理解到你这是ASCII码值里的97,不是一个合法的地址,所以会发生错误

   12.printf("%d\n",strlen(&p));//随机值

   &p是指针p的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   13.printf("%d\n",strlen(&p+1));//随机值

   &p+1是p后面的地址,strlen()是求字符的长度,遇见'\0'停止,由于arr中是单个字符,没有'\0',所以strlen()不知道什么时候停下

   14. printf("%d\n",strlen(&p[0]+1));//5

   &p[0]+1)是第二个元素的地址,到'\0'有5个元素,所以长度为5

题五

1. #include<stdio.h>
2. int main()
3. {
4. int arr[3][4]={0};
5. printf("%d\n",sizeof(arr));//48 
6. printf("%d\n",sizeof(arr[0][0]));//4
7. printf("%d\n",sizeof(arr[0]));//16 
8. printf("%d\n",sizeof(arr[0]+1));//8 
9. printf("%d\n",sizeof(*(arr[0]+1)));//4
10. printf("%d\n",sizeof(*(arr+1)));//16 
11. printf("%d\n",sizeof(&arr[0]+1));//8 
12. printf("%d\n",sizeof(*(&arr[0]+1)));//16 
13. printf("%d\n",sizeof(*arr));//16
14. printf("%d\n",sizeof(arr[3]));//16 
15. }

注:作为二维数组的数组名,没有&,没有单独放在sizeof中,所以就是第一行的数组名,解引用就是第一行的元素

   1.printf("%d\n",sizeof(arr));//48

   sizeof(arr)计算的是整个数组的大小

   2.printf("%d\n",sizeof(arr[0][0]));//4

   arr[0][0]第一个元素,大小为4

   3.printf("%d\n",sizeof(arr[0]));//16

   arr[0]第一行的数组名,看成一维数组,sizeof(arr[0])求的是第一行的元素的大小,大小为16

   4.printf("%d\n",sizeof(arr[0]+1));//8

   arr[0]+1第二行的数组名  ,sizeof(arr[0]+1)求的是第二行的元素的大小,大小为16

   5.printf("%d\n",sizeof(*(arr[0]+1)));//4

   arr[0]+1第二行的数组名 ,*(arr[0]+1)是第二行第一个元素,大小为4

   6.printf("%d\n",sizeof(*(arr+1)));//16

   *(arr+1)是第二行的所有元素,大小为16

   7.printf("%d\n",sizeof(&arr[0]+1));//8

    &arr[0]是第一行的地址,&arr[0]+1是第二行的地址,32位平台是4,64位平台是8

   8.printf("%d\n",sizeof(*(&arr[0]+1)));//16

   *(&arr[0]+1)是第二行的元素,大小为16    

   9.printf("%d\n",sizeof(*arr));//16

  arr是第一行的数组名,*arr是第一行的元素,大小为16

  10.printf("%d\n",sizeof(arr[3]));//16

   arr[3]其实是第四行的地址,但实际上不存在,但也能通过类型计算其的大小

例如:

short s=5;

int a=4

printf("%d ",sizeof(s=a+6));//还是以s类型是,short,

printf("%d ",s);//5 sizeof()中的表达式是不参与运算的

题六

1. #include<stdio.h>
2. int main()
3. {
4. int a[3][2]={(0,1),(2,3),(4,5)};//a[0]为1,3 a[1]为5,0 a[2]为2,4
5. int* p;
6.     p=a[0];//a[0]首元素的地址
7. printf("%d\n",p[0]);//p[0]等于*(p+0);
8. return 0;
9. }

int a[3][2]={(0,1),(2,3),(4,5)};这种逗号表达式的写法非常特殊,我们可以把这个二维数组等同于a[3][2]={1,3,5,0,2,4}

题七

1. #include<stdio.h>
2. int main()
3. {
4. int aa[2][5]={1,2,3,4,5,6,7,8,9,10};
5. int* ptr1=(int *)(&aa+1);
6. int* ptr2=(int *)(*(aa+1));
7. printf("%d %d ",*(ptr1-1),*(ptr2-1));
8. return 0;
9. }

int* ptr1=(int *)(&aa+1):

&aa+1是数组后面的的地址,(int *)是将其强制转化为整形的地址,其实在这里意义不大,因为&aa+1本身就是整形地址类型

int* ptr2=(int *)(*(aa+1)):

aa+1是第二行的地址,*(aa+1)第二行第一个元素

printf("%d %d ",*(ptr1-1),*(ptr2-1)):

*(ptr1-1)就是最后一个元素的值10,*(ptr2-1)是第一行最后一个数的值5

题八

1. #include<stdio.h>
2. int main()
3. {
4. char* a[]={"work","at","alibaba"};
5. char** pa=a;
6.     pa++;
7. printf("%s\n",*pa);
8. return 0;
9. }

** pa存储的就是数组a的首元素地址, pa++就是第二个元素的地址,在解引用就是"at"了

题九

1. #include<stdio.h>
2. int main()
3. {
4. char* c[]={"ENTER","NEW","POINT","FIRST"};
5. char** cp[]={c+3,c+2,c+1,c};
6. char*** cpp=cp;
7. printf("%s\n",**++cpp);
8. printf("%s\n",*--* ++cpp +3);
9. printf("%s\n",*cpp[-2]+3);
10. printf("%s\n",cpp[-1][-1]+1);
11. return 0;
12. }

printf("%s\n",**++cpp):

++cpp就是cp[1]的地址,*++cpp这样解引用就是c[2]的地址,再解引用就是“POINT:

printf("%s\n",*--* ++cpp +3):

++cpp就是cp[2]的地址,* ++cpp得到的是c[1]的地址,--* ++cpp得到的是c[0]的地址,*--* ++cpp这样解引用就是“ENTER”,*--* ++cpp +3就是“ER”。

printf("%s\n",*cpp[-2]+3):

**(cpp-2)+3,cpp就是cp[2]的地址,cpp-2就是cp[0]的地址,**(cpp-2)就是“FIRST”,**(cpp-2)+3就是“ST”

printf("%s\n",cpp[-1][-1]+1):

*(*(cpp-1)-1)+1,cpp是cp[2]的地址,cpp-1就是cp[1]的地址,*(cpp-1)就是c[2]的地址,*(cpp-1)-1就是c[1]的地址,*(*(cpp-1)-1)就是“NEW”,*(*(cpp-1)-1)+1为“EW”

最后这道题,是这题里最具有价值题,是最浓缩的题,当然难度是相当大的,理解起来也比较复杂,其实解这种指针的题,我们可以画图,比如最后一道题

46EE0121-B428-432F-992B-EE218700AB11.jpeg

画图之后我们可以清晰了解这些指针怎么’‘运行的‘’。

🐶🐶🐶指针学习的内容差不多就是这些了,希望大家看这些关于指针的题,能够帮助帮助大家对指针的理解,如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 💖💖💖

文章知识点与官方知识档案匹配



相关文章
|
4月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
90 0
|
2月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
124 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
2月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
182 9
|
2月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
64 7
|
3月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
268 13
|
3月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
90 11
|
3月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
3月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
220 3
|
3月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
3月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
72 1