C语言基础(十一)---数组指针与指针数组

数组指针
(1)、定义
  • 概念:数组指针是指向整个数组的指针,本质上还是指针(地址)

  • 特点:

    1. 先有数组,后有指针

    2. 它指向的是一个完整的数组

(2)、一维数组指针
  • 语法:(必须给*指针变量名带括号,[]的优先级高于*)

     数据类型 (*指针变量名)[数组容量];
  • 案例:

     int arr[] = {11, 22, 33, 44, 55};
     ​
     int *p = arr;     //这里是指向数组的首地址
     p++;     //可以进行自增操作,指向首元素的下一个元素
     ​
     ​
     //对数组指针 不要随意使用自增操作,不然会下标越界,成为野指针(指向一处未知区域)
     //数组指针:指向数组的指针(这里是指向整个数组,不是数组的某个元素)
     int main()
     {
         //一维数组指针
         //先有数组,再有指针
         //指针不能独立存在,必须依赖与现有的常量或者变量空间
         
         int arr[] = {100, 200, 300};
         
         //获取数组的大小
         int len = sizeof(arr) / sizeof(arr[0]);
         
         //指针变量指向数组元素:此时指针指向的是数组中的第一个元素,此时指针存储的值是首元素的地址值
         int *q = arr;
         
         //定义一个数组指针///
         //数组指针指向整个数组:此时指针指向的是整个数组,此时指针存储的值是首元素的地址值
         int (*p)[len] = &arr;     //数组名和&在一起就代表整个数组的地址,数组名单独出现就代表的数组首元素的地址
         
         //此时不能p++,否则会下标越界,产生野指针
         printf("%p, %p, %p\n", p, &arr, arr);     //结果一样,指向的都是数组元素首地址
         
         
         如何访问数组指针//
         printf("%d\n", (*p)[0]);     //100
         
         //遍历数组指针
         for(int i = 0; i < len; i++)
         {
             printf("%-4d", (*p)[i]);     //数组指针本质是指针所以我们需要添加小括号提升指针的优先级(默认数组优先)
         }
         
     }
  • 我们之前所学的是指向数组元素的指针,本质上是指针变量,现在我们学的是指向数组的指针,叫做数组指针

  • 注意:

    • 指针变量指向数组元素:此时指针指向的是数组中的第一个元素,此时指针存储的值是首元素的地址值 int *q = arr;

    • 数组指针指向整个数组:此时指针指向的是整个数组,此时指针存储的值是首元素的地址值 int (*p)[len] = &arr;

    • arr默认指向首元素,&arr指向整个数组

(3)、二维数组指针
  • 语法:

     数据类型 (*指针变量名)[行容量][列容量];
  • 案例:

    • 写法1:不推荐

       int arr[][3] = {10, 20, 30, 100, 200, 300, 1000, 2000, 3000};
       ​
       //定义一个数组指针指向二维数组arr
       int (*p)[][3] = &arr;     //数组指针指向二维数组,不推荐
    • 写法2:推荐

       int arr[][3] = {10, 20, 30, 100, 200, 300, 1000, 2000, 3000};
       ​
       定义一维数组指针/
       int (*p)[3] = arr;     //数组指针指向二维数组首行,推荐,默认指向第一行
       ​
       //p++;      //可以进行p++,加一次就往下指一行
       ​
       ///遍历方法1(指针数组方式)/
       for(int i = 0; i < 3; i++)
       {
           for(int j = 0; j < 3; j++)
           {
               printf("%-5d", p[i][j]);     //arr的地址等于p存储的地址,也就意味着p等价于arr
           }   
           printf("\n");
       }
       ​
       /遍历方法2(数组指针解引用)
       for(int i = 0; i < 3; i++)
       {
           for(int j = 0; j < 3; j++)
           {
               printf("%-5d", *(*(p + i) + j));     //先偏移行再偏移列。*(p+i) → p[i],     *(p[i] + j) → p[i][j]
           }
       }
       printf("\n");
       ​
       //遍历方法3(混合法)///
       for(int i = 0; i < 3; i++)
       {
           for(int j = 0; j < 3; j++)
           {
               printf("%-5d", (*(p + i))[j]);     
           }
       }
       }
(4)、指针和数组中符号优先级

() > [] > *

(5)、通过指针引用二维数组
表示形式 含义
a 二维数组名,相当于&a[0],指向一维数组a[0](0行首地址)
a[0]、*(a+0)、 *a &a[0] [0].0行0列元素地址
a+1、&a[1] 1行首地址
a[1]、*(a+1) &a[1] [0].1行0列元素的地址
a[1]+2、&a[1] [2]、*(a+1)+2 1行2列元素的地址
*(a[1]+2)、 *( *(a+1)+2)、a[1] [2] 1行2列元素a[1] [2]的值

  • 注意:二维数组中,数组整体的地址值 == 数组中0行元素的地址值 == 数组中0行0列元素的地址值

(6)、案例
  • 案例1:最简单的方法

    • 需求:用指向元素的指针变量输出二维数组元素的值

    • 代码:

       //定义一个普通的二维数组
       int arr[3][4] = {10, 20, 30, 40, 100, 200, 300, 400, 1000, 2000, 3000, 4000};
       ​
       //定义一个指针变量,用来接收二维数组的元素
       int *p = arr[0];     //列 10 的位置
       ​
       //获取元素个数
       //int len = (sizeof(arr) / sizeof(arr[0])) * (sizeof(arr[0]) / sizeof(arr[0][0]));
       ​
       int len = sizeof(arr) / sizeof(arr[0][0]);
       ​
       //遍历数组
       //for(; p < arr + sizeof(arr) / sizeof(arr[0]); p++)      //会报警告,不影响使用
       for(; p < arr[0] + len; p++)
       {
           printf("%-6d", *p);
           
           //每四个换行
           if((p - arr[0]) % 4 == 0 )     //p2-p1 = n
               printf("\n");
       }
       printf("\n");
  • 案例2

    • 需求:数组指针-输出二维数组任一行任一列元素的值

    • 代码:

       #include 
       ​
       /**
        * 需求:数组指针-输出二维数组任一行任一列元素的值
        */
       void arr_fun2()
       {
           //定义一个二维数组
           int arr[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23};
           
           //创建一个一维的数组指针指向一个二维的数组
           int (*p)[4] = arr;     //等价于&arr[0],p代表我们这个二维数组
           
           //创建两个变量,代表我们对应数据的行和列
           int row, col;
           
           //通过控制台来输入
           printf("请输入行号和列号:\n");
           scanf("%d, %d", &row, &col);
           
           printf("arr[%d][%d] = %d\n", row, col, *(*(p + row) + col));     //*(*(p + row) + col)     → *(p[row]+col)  →  p[row][col]
           
       }
       ​
       int main()
       {
           arr_fun2();
           return 0;
       }
2、指针数组
(1)定义
  • 概念:指针数组是一个数组,数组中的每一个元素都是一个指针

  • 特点:

    • 先有指针,后有数组

    • 指针数组的本质是一个数组,只是数组中的元素类型是指针

  • 语法:

     数据类型 *数组名[容量];
  • 案例:

     //定义三个变量
     int a = 10, b = 20, c = 30;
     ​
     //定义指针数组,指针数组是用来存储指针的
     int *arr[3] = {&a, &b, &c};     //int是abc的类型
     //指针数组里的元素不要直接用,因为是地址,如果要使用的话要先解引用
     ​
     //获取数组大小
     int len = sizeof arr / sizeof arr[0];//sizeof和return是运算符,可以带括号也可以不带
     ​
     //遍历数组
     for(int i = 0; i < len; i++)
     {
         printf("%-3d", *arr[i]);
     }
     ​
     printf("\n");
     ​
  • 建议:我们一般使用指针数组处理字符串

3、数组指针与指针数组的区别
对比项 指针数组 数组指针
定义 数组元素均为指针的数组 指向一个数组的指针
存储内容 存储多个指针,每个元素指向不同内存地址 存储单个指针,指向一个完整的数组(首地址)
内存分配 每个指针元素独立分配内存,可能分散 指向的数组内存连续,指针本身存储数组首地址
语法示例 int *arr[5];(元素为5个int类型的指针) int (*ptr)[5];(指向含5个int元素的数组的指针)
访问方式 通过下标访问指针元素,再解引用:*arr[i] 先解引用指针得到数组,再访问元素:(*ptr)[i]或ptr[0] [i]
使用场景 管理多个独立指针(如字符串数组、动态结构体数组) 操作多维数组(如传递二维数组的行指针)
示例代码 int a = 1, b = 2; int *arr[] = {&a, &b}; int arr[2] [3] = {1, 2, 3, 4, 5, 6}; int (*ptr)[3] = arr;

你可能感兴趣的:(c语言,java,算法)