指针与数组的连接

  1. int main()
  2. {
  3. int a[5] = {1,2,3,4,5};
  4. int *p1,*p2,*p3;
  5. // 因为 a 本身就代表了数组的地址,所以此处,& 必须省略
  6. p1 = a;
  7. p2 = &a[0];
  8. p3 = &a[3];
  9. printf("%p,%p,%p\n",p1,p2,p3); //000000000062FDF0,000000000062FDF0,000000000062FDFC
  10. }
  1. p 的地址就是数组 a 的地址,就是 a[0]的地址
    1. int main()
    2. {
    3. int a[5] = {1,2,3,4,5};
    4. int *p;
    5. p = a;
    6. printf("%d,%d,%d\n",p,a,&a[0]); //6487552,6487552,6487552
    7. return 0;
    8. }

    指针的算术运算

    image.png
  1. int main()
  2. {
  3. int a[10],*p;
  4. // 用指针指向数组第一项的地址
  5. p = &a[0];
  6. *p = 5;
  7. p[1] = 6;
  8. printf("%d\n",a[0]); //5
  9. printf("%d\n",a[1]); //6
  10. }

指针的算术运算包括

  1. 指针加上整数
  2. 指针减去整数
  3. 两个指针相减
  1. // 指针加
  2. int main()
  3. {
  4. int a[10]={1,2,3,4,5,6,7,8,9,10};
  5. int *p,*q;
  6. p = &a[0];
  7. // 将 p 后移三位的地址赋给 q
  8. q = p+3;
  9. // p 后移六位
  10. // 注意加不能超过数组的长度,否则出现不可预知的值
  11. p += 6;
  12. printf("p指向的值:%d,q指向的值:%d\n",*p,*q);
  13. return 0;
  14. }
  1. // 指针减
  2. int main()
  3. {
  4. int a[10]={1,2,3,4,5,6,7,8,9,10};
  5. int *p,*q;
  6. p = &a[10];
  7. q = p-3;
  8. p -= 6;
  9. printf("p指向的值:%d,q指向的值:%d\n",*p,*q);
  10. return 0;
  11. }
  12. // 输出
  13. p指向的值:5,q指向的值:8
  1. // 指针相减,表示指针间的距离,也是数组元素中的个数
  2. int main()
  3. {
  4. int a[10]={1,2,3,4,5,6,7,8,9,10};
  5. int *p,*q;
  6. p = &a[10];
  7. q = &a[0];
  8. printf("p-q:%d\n",p-q);
  9. return 0;
  10. }
  11. // 输出
  12. p-q:10

note

  1. 只有指针指向同一数组时才有意义

指针用于数组处理

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

* 和 ++ 运算符结合
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[10]={0};
  5. int *p;
  6. int i=0;
  7. for(p = &a[0];p<&a[10];)
  8. {
  9. // 相当于 *(p++) ,也就是先对 p 移动位置,在取 p 值做加法运算
  10. *p++ = i;
  11. i++;
  12. }
  13. for(p = &a[0];p<&a[10];p++)
  14. {
  15. printf("%d ",*p);
  16. }
  17. return 0;
  18. }
  19. // 输出
  20. 0 1 2 3 4 5 6 7 8 9

用数组名作为指针

  1. 数组名作为指向数组的第一个元素的指针

如,a+i = &a[i],*(a+1) = a[i]

  1. #include <stdio.h>
  2. int main()
  3. {
  4. int a[10]={1,2,3,4,5,6,7,8,9,10};
  5. int *p;
  6. printf("a的值:%d\n",*a);
  7. printf("a的地址:%d",a);
  8. return 0;
  9. }
  10. // 输出
  11. a的值:1
  12. a的地址:6684144
  1. // 用指针作为数组名
  2. #include <stdio.h>
  3. int main()
  4. {
  5. int a[10]={1,2,3,4,5,6,7,8,9,10};
  6. int *p;
  7. p = a;
  8. printf("a的值:%d\n",*p);
  9. printf("a的地址:%d",p);
  10. return 0;
  11. }
  12. // 输出
  13. a的值:1
  14. a的地址:6684144

指针和多维数组

  1. 多维数组就是数组里面的元素还是数组
  2. 在二维数组中直接书写 a 就是一个地址

    处理多维数组的元素

  3. C 语言始终按照行主序的顺序存储二维数组

image.png

  1. // 方式一:嵌套循环
  2. int main(){
  3. int row,col;
  4. int a[5][5] = {
  5. {1,2,3,4,5},
  6. {6,7,8,9,10},
  7. {11,12,13,14,15},
  8. {16,17,18,19,20},
  9. {21,22,23,24,25},
  10. };
  11. for(row=0;row<5;row++){
  12. for(col=0;col<5;col++){
  13. a[row][col]=0;
  14. }
  15. };
  16. printf("%d\n",a[0][0]); // 可以看到值已经被修改成 0 了
  17. }
  18. // 方式二:模拟成一维数组
  19. int row,col;
  20. int a[5][5] = {
  21. {1,2,3,4,5},
  22. {6,7,8,9,10},
  23. {11,12,13,14,15},
  24. {16,17,18,19,20},
  25. {21,22,23,24,25},
  26. };
  27. // 二维数组在用指针指向的时候,不能写成 int *p = a 的形式
  28. // 只有一维的时候才可以这样
  29. int *p = &a[0][0];
  30. for(;p<&a[4][4];p++){
  31. *p=0;
  32. }
  33. printf("%d\n",a[0][0]); // 可以看到值已经被修改成 0 了

【注】二维数组在用指针指向的时候,不能写成 int *p = a 的形式。只有一维的时候才可以这样

处理多维数组的行

  1. 想要让指针定位到某一样,我们可以这样写 p=&a[i][0] 或者 p=a[i]

    1. int row,col;
    2. int a[5][5] = {
    3. {1,2,3,4,5},
    4. {6,7,8,9,10},
    5. {11,12,13,14,15},
    6. {16,17,18,19,20},
    7. {21,22,23,24,25},
    8. };
    9. printf("%d",a[1][0]) ;
    10. int (*p)[5] = a;
    11. printf("%d,%d\n",p[0][0],**a);

    【注】%p 是以十六进制输出指针的内存地址

    指针数组和数组指针

  2. 指针数组,首先是一个数组,数组的元素都是指针,int *p1[10],因为 [] 优先级高,则说明是先 p1[10],再 *

  3. 数组指针,首先是一个指针,一个指针指向数组,int (*p1)[10],因为()优先级高,所以是先指针,再数组

第十二章 指针和数组 - 图3

  1. 关于 a 和 &a

&a 是整个数组的首地址,a 是数组首元素的首地址,值相同但意义不同,但是 = 两边需要数据类型必须一致,所以不要误用