C语言学习第22篇---数组和指针的关系剖析

举报
CodeAllen 发表于 2021/10/30 01:08:36 2021/10/30
【摘要】 知识来源主要是陈正冲老师的《C语言深度解剖》及Delphi Tang老师的《C语言剖析》和《征服C指针》,《C和指针》,有兴趣的朋友可以看我置顶文章获取   数组的本质: 数组是一段连续的内存空间数组的空间大小为sizeof(array_type)*array_size数组名可以看做指向数组的第一个元素的常量指针(只是理...

知识来源主要是陈正冲老师的《C语言深度解剖》及Delphi Tang老师的《C语言剖析》和《征服C指针》,《C和指针》,有兴趣的朋友可以看我置顶文章获取

 

数组的本质:

  • 数组是一段连续的内存空间
  • 数组的空间大小为sizeof(array_type)*array_size
  • 数组名可以看做指向数组的第一个元素的常量指针(只是理解,其实是错的,参见《征服C指针》)

 

实验1:a+1的结果是什么?


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[5] = {0};
  5. int* p = NULL;
  6. printf("a = 0x%X\n", (unsigned int)(a));
  7. printf("a + 1 = 0x%X\n", (unsigned int)(a + 1));
  8. printf("p = 0x%X\n", (unsigned int)(p));
  9. printf("p + 1 = 0x%X\n", (unsigned int)(p + 1));
  10. return 0;
  11. }

 

指针是一种特殊的变量,与整数的远算法则为

理解:

当指针p指向一个同类型的数组的元素时:p+1将指向当前元素的下一个元素:p-1指向当前元素的上一个元素

 

指针的运算:

  • 指针之间只支持减法运算
  • 参与运算的指针类型必须相同

理解:

  1. 只有当两个指针指向同一个数组中的元素时,指针相减才有意义,其意义是指针所指元素的下标差
  2. 当两个指针指向的元素不在同一个数组中时,结果未定义

 

指针的比较:

  • 指针可以进行关系运算(< , <= , > , >=)
  • 指针关系运算的前提是同时指向同一个数组中的元素
  • 任意两个指针之间的比较运算(==,!=)无限制
  • 参与比较运算的指针类型必须相同

 

实验2:指针运算


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. char s1[] = {'H', 'e', 'l', 'l', 'o'};
  5. int i = 0;
  6. char s2[] = {'W', 'o', 'r', 'l', 'd'};
  7. char* p0 = s1;
  8. char* p1 = &s1[3];
  9. char* p2 = s2;
  10. int* p = &i;
  11. printf("%d\n", p0 - p1);
  12. printf("%d\n", p0 + p2);
  13. printf("%d\n", p0 - p2);
  14. printf("%d\n", p0 - p);
  15. printf("%d\n", p0 * p2);
  16. printf("%d\n", p0 / p2);
  17. return 0;
  18. }

 

实验3:指针运算的应用


  
  1. #include <stdio.h>
  2. #define DIM(a) (sizeof(a) / sizeof(*a))
  3. int main()
  4. {
  5. char s[] = {'H', 'e', 'l', 'l', 'o'};
  6. char* pBegin = s;
  7. char* pEnd = s + DIM(s); // Key point
  8. char* p = NULL;
  9. printf("pBegin = %p\n", pBegin);
  10. printf("pEnd = %p\n", pEnd);
  11. printf("Size: %d\n", pEnd - pBegin);
  12. for(p=pBegin; p<pEnd; p++)
  13. {
  14. printf("%c", *p);
  15. }
  16. printf("\n");
  17. return 0;
  18. }

 

 

数组的访问方式有两种

  • 下标的方式
  • 指针的形式

 

分析下两种方式的不同:(下标形式对于阅读代码更优)

  • 指针一固定增量在数组中移动时,效率高于下边形式
  • 指针增量为1且硬件具有硬件增量模型时,效率更高
  • 下标形式与指针形式的转换:

 

实例4:数组的访问方式


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[5] = {0};
  5. int* p = a;
  6. int i = 0;
  7. for(i=0; i<5; i++)
  8. {
  9. p[i] = i + 1;
  10. }
  11. for(i=0; i<5; i++)
  12. {
  13. printf("a[%d] = %d\n", i, *(a + i));
  14. }
  15. printf("\n");
  16. for(i=0; i<5; i++)
  17. {
  18. i[a] = i + 10;
  19. }
  20. for(i=0; i<5; i++)
  21. {
  22. printf("p[%d] = %d\n", i, p[i]);
  23. }
  24. return 0;
  25. }

 

实验5:数组与指针的差别


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. //extern int* a;
  5. int a[] = {1, 2, 3, 4, 5};
  6. printf("&a = %p\n", &a);
  7. printf("a = %p\n", a);
  8. printf("*a = %d\n", *a);
  9. return 0;
  10. }
  11. 、、、、、、、、、、、、、、、、、
  12. int a[] = {1, 2, 3, 4, 5};

 

a和&a的区别

  • a为数组首元素的地址
  • &a为整个数组的地址
  • a和&a的区别在于指针运算

 

实例6:指针运算的经典问题


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[5] = {1, 2, 3, 4, 5};
  5. int* p1 = (int*)(&a + 1);
  6. int* p2 = (int*)((int)a + 1);
  7. int* p3 = (int*)(a + 1);
  8. printf("%d, %d, %d\n", p1[-1], p2[0], p3[1]);
  9. return 0;
  10. }
  11. // A. 数组下标不能是负数,程序无法运行
  12. // B. p1[-1]将输出随机数,p2[0]输出2, p3[1]输出3
  13. // C. p1[-1]将输出乱码, p2[0]和p3[1]输出2

 

数组函数:数组作为函数参数时,编译器将其编译为对应的指针

 

实例7:数组参数探究


  
  1. #include <stdio.h>
  2. void func1(char a[5])
  3. {
  4. printf("In func1: sizeof(a) = %d\n", sizeof(a));
  5. *a = 'a';
  6. a = NULL;
  7. }
  8. void func2(char b[])
  9. {
  10. printf("In func2: sizeof(b) = %d\n", sizeof(b));
  11. *b = 'b';
  12. b = NULL;
  13. }
  14. int main()
  15. {
  16. char array[10] = {0};
  17. func1(array);
  18. printf("array[0] = %c\n", array[0]);
  19. func2(array);
  20. printf("array[0] = %c\n", array[0]);
  21. return 0;
  22. }

 

小结:

文章来源: allen5g.blog.csdn.net,作者:CodeAllen的博客,版权归原作者所有,如需转载,请联系作者。

原文链接:allen5g.blog.csdn.net/article/details/80463348

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。