C语言-数组指针和指针数组

发布于:2025-03-23 ⋅ 阅读:(17) ⋅ 点赞:(0)

指针

数组指针与指针数组

数组指针
定义

概念:数组指针是指向数组的指针,本质上还是指针

特点:

①先有数组,后有指针

②它指向的是一个完整的数组

一维数组指针

语法:

 数据类型 (*指针变量名)[容量];

案例:

 /*int arr[] = {11,22,33,44,55};
 ​
 int *p = arr;
 p++;
 */
 ​
 ​
 /*************************************************************************
   > File Name:    demo01.c
   > Author:       赵生鑫
   > Description:  
   > Created Time: 2025年03月20日 星期四 09时48分24秒
  ************************************************************************/
 ​
 #include <stdio.h>
 ​
 /*
  *
  *数组指针:指向数组的指针(这里指向整个数组,不是数组的某个元素)
  *
  * */
 ​
 int main(int argc,char *argv[])
 {
     //一维数组指针
     //先有数组,再有指针
     
     //指针不能独立存在,必须依赖与现有的常量或者变量空间
     int arr[] = {100,200,300};
 ​
     //获取数组大小
     int len = sizeof(arr) / sizeof(arr[0]);
 ​
     //指针变量指向数组元素:此时指针指向的时数组中的第一个元素,此时指针存储的值是首元素的地址值
     //数组指针指向整个数组:此时指针指向的是整个数组,此时指针存储的值是首元素的地址值
 ​
     //定义一个数组指针
     int (*p)[3] = &arr;//arr默认指向首元素,&arr指向整个数组
 ​
     //p++  此时不能p++,否则会越界
     
     printf("%p,%p,%p\n",p,&arr,arr);//输出3个地址相等
 ​
     //如何访问数组指针
     printf("%d\n",(*p)[2]);
 ​
     //遍历数组指针
     for ( int i = 0;i < len ;i++)
     {
         
         printf("%-6d",(*p)[i]);//数组指针本质是指针,所以我们需要添加()提升指针优先级(默认数组优先)
     }
     printf("\n");
     
     return 0;
 }

我们之前所学的是指向数组元素的指针,本质上是指针变量;现在我们学的是指向数组的指针,叫做数组指针

二维数组指针

语法:

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

案例:

  • 写法1

     /*************************************************************************
       > File Name:    demo02.c
       > Author:       赵生鑫
       > Description:  
       > Created Time: 2025年03月20日 星期四 10时17分55秒
      ************************************************************************/
     ​
     #include <stdio.h>
     ​
     int main(int argc,char *argv[])
     {
         int arr[][3] = {11,22,33,44,55,66,77,88,99};
     ​
         //定义一个数组指针指向二维数组arr
         //int (*p)[][3] = &arr;   数组指针指向二维数组,不推荐
         
         int (*p)[3] = arr;//数组指针指向二维数组首行,推荐
     ​
     ​
         //遍历(数组方式)
         for(int i = 0; i < 3;i++)
         {
             for(int j = 0;j < 3;j++)
             {
                 printf("%-6d",p[i][j]);//arr的地址  等于  p存储的值,也就意味着p等价与arr
             }
             printf("\n");
         }
         
     ​
         //p++;//此时是可以使用,因为p指向的是arr中的行,默认为首行
         
         return 0;
     }
     ​
  • 写法2

     /*************************************************************************
       > File Name:    demo02.c
       > Author:       赵生鑫
       > Description:  
       > Created Time: 2025年03月20日 星期四 10时17分55秒
      ************************************************************************/
     ​
     #include <stdio.h>
     ​
     int main(int argc,char *argv[])
     {
         int arr[][3] = {11,22,33,44,55,66,77,88,99};
     ​
         //定义一个数组指针指向二维数组arr
         //int (*p)[][3] = &arr;   数组指针指向二维数组,不推荐
         
         int (*p)[3] = arr;//数组指针指向二维数组首行,推荐
     ​
     ​
         int rows = sizeof(arr) / sizeof(arr[0]);
         int cols = sizeof(arr) / sizeof(arr[0]);
     ​
         for(int i = 0;i < rows;i++)
         {
             for(int j = 0;j < cols;j++)
             {
                 //三种写法
                 //1.指针数组语法
                 printf("%-6d",p[i][j]);
     ​
                 //2.指针解引用
                 printf("%-6d",*(*(p + i) + j));
     ​
                 //3.混合法
                 printf("%-6d",(*(p + i))[j]);//解引用符*和数组访问符[]在一起时,默认的[]优先级高
                 
             }
             printf("\n");
         }
     ​
         
     ​
         //p++;//此时是可以使用,因为p指向的是arr中的行,默认为首行
         
         return 0;
     }
     ​
指针和数组中的符号优先级

() > [] > *

通过指针引用二维数组

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

案例

案例1

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

  • 代码:

     /*************************************************************************
       > File Name:    demo03.c
       > Author:       赵生鑫
       > Description:  
       > Created Time: 2025年03月20日 星期四 11时46分00秒
      ************************************************************************/
     ​
     #include <stdio.h>
     ​
     int main(int argc,char *argv[])
     {
         //定义一个普通二维数组
         int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};
     ​
         //定义一个指针变量,用来接收二维数组的元素
         int *p = arr[0];//0列的位置
     ​
         //获取元素个数
         int len = (sizeof(arr) / sizeof(arr[0])) * (sizeof(arr[0]) / sizeof(arr[0][0]));
         
         //遍历数组
         for(;p < arr[0]+len;p++)
         {
             //每4个换行
             if((p - arr[0]) % 4 == 0)
                 printf("\n");
             printf("%-6d",*p);
         }
         printf("\n");
     ​
     ​
         return 0;
     }
     ​
     ​
指针数组

定义:指针数组是一个数组,数组中的每一个元素都是一个指针

特点:

  • 先有指针,后有数组

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

语法:

 数据类型 *数组名[容量];
 #include <stdio.h>
 ​
 int main()
 {
     //定义三个变量
     int a = 10,b = 20,c = 30;
     
     //定义指针数组,指针数组是用来存储指针
     int *arr[3] = {&a,&b,&c};
     
     //获取数组大小
     int len = sizeof(arr) / sizeof(arr[0]);
     
     //遍历数组
     for(int i = 0;i < len; i++)
     {
         pritnf("%-3d",*arr[i]6);
     }
     return 0;
 }

建议:我们一般使用指针数组处理字符串。

数组指针与指针数组的区别

字符数组和字符指针

字符串实现

再C语言中,表示一个字符串有以下两种方式:

①数组形式:用字符数组存放一个字符串

②指针形式:用字符指针指向一个字符串

案例
 #include <stdio.h>
 ​
 /*
 方式1:使用字符数组实现字符串
 */
 void str_test1()
 {
     //定义一个伪字符串
     char str[] = "  I LOVE YOU";
     
     printf("%s\n",str);
 }
 ​
 ​
 /*
 方式2:使用字符指针实现字符串
 */
 void str_test2()
 {
     //定义一个伪字符串
     char *str = "I LOVE YOU";
     
     printf("%s\n",str);
 }
 ​
 ​
 ​
 int main()
 {
     str_test1();
     str_test2();
     return 0;
 }

注意:字符数组和字符指针变量都能实现字符串的存储与运算。(字符指针→字符类型的指针变量)

字符数组和字符指针的联系
概念
  • 字符数组由元素组成,每个元素中存放一个字符,而字符指针变量中存放的是地址(可以作为函数参数)

  • 只能对字符数组中的各个元素赋值,而不能用赋值语句对整个字符数组赋值

     char arr[3] = {};
     arr[2] = 'A';//正确,对字符数组中的元素赋值
     ​
     arr = {'E','D','F'};//错误,对整个数组赋值(可以理解为数组就是一个常量,一旦创建,就无法改变)
  • 字符数组名虽然代表地址,但数组名的值不能改变,因为数组名是常量(参照上面案例)

  • 对应字符串中的字符的存取,可以用下标法,也可以用指针法。

案例
 #include <stdio.h>
 ​
 int mian()
 {
     //使用两种方式测试字符串
     char str1[] = "你好,佩奇!";
     char *str2 = "你好,乔治!";
     
     //赋值测试
     str1 = "你好啊,佩奇!!";//数组一旦创建就无法改变其值,可以理解为数组名是常量
     str2 = "你好啊,乔治!!";
     
     //打印测试
     printf("%s,%s\n",str1,str2);
     
     /*//以下代码会报错
     //给字符串赋值
     char *str3 = NULL;//未初始化的指针,指针一定要有指向,需要指向一个具体的内存空间
     printf("请输入一个符串:\n");
     scanf("%s",str3);
     printf("%s\n ",str3);
     */
     
     char a[] = "I LOVE YOU";
     char *b = "I LOVE YOU";
     
     //使用下标法和指针法分别访问字符串
     printf("%c,%c\n,%c\n",a[2],*(a+2),b[2],*(b+2))
     
     return 0;
 }
字符串作为形式参数
定义
  • 实参与形参都可以是字符数组

     void fun(char str[],int len){...}
     void mian()
     {
         char str[] = "hello";
         fun(str,sizeof(str) / sizeof(str[0]))
     }
  • 实参用字符数组,形参用字符指针

     void fun(char *str,int len){...}
     void mian()
     {
         char *str = "hello";
         fun(str,sizeof(str) / sizeof(str[0]))
     }
  • 形参和实现都是指针变量(在函数内部中不对字符串中的字符做修改)

     void fun(char *str,int len)
     {
         //在函数内部中不对字符串中的字符做修改,否则报段错误
         //*(str + 2) = 'A';
         //str[2] = 'A';
         printf("%s\n",str);
     }
     void mian()
     {
         char *str = "hello";
         fun(str,sizeof(str) / sizeof(str[0]))
     }
  • 实参是指针类型,形参是字符数组(在函数内部中不对字符串中的字符做修改)

     void fun(char str[],int len)
     {
         //在函数内部中不对字符串中的字符做修改,否则报段错误
         //*(str + 2) = 'A';
         //str[2] = 'A';
         printf("%s\n",str);
     }
     void mian()
     {
         char *str = "hello";
         fun(str,sizeof(str) / sizeof(str[0]))
     }
注意

1.字符数组在创建的时候,会在内存中开辟内存空间,内存空间可以存放字符数据;字符指针在创建的时 候,需要依赖于字符数组,字符指针在内存开辟的内存空间中,存放的是数组元素的地址。字符指针的 创建依赖于字符数组,字符数组可以独立存在,而字符指针不能独立存在。 2.字符数组可以初始化,但是不能赋值;字符指针可以初始化,也可以赋值。

案例
案例1
  • 需求:字符指针作为函数参考:用函数调用实现字符串的复制及长度计算

  • 代码:

     /*************************************************************************
       > File Name:    demo04.c
       > Author:       赵生鑫
       > Description:  
       > Created Time: 2025年03月20日 星期四 16时55分04秒
      ************************************************************************/
     ​
     #include <stdio.h>
     ​
     /*
      *
      *定义一个函数,实现字符串的拷贝,返回字符串的长度
      *@param source拷贝的源字符串
      *@param target需要拷贝保存字符串的目标字符串
      *@return 字符串长度
      *
      * */
     int str_copy(const char *source,char *target)
     {
         //定义一个循环变量
         register int i = 0;
     ​
         //循环的遍历
         while(source[i] != '\0')
         {
             //实现拷贝
             *(target + i) = *(source + i);//指针法
     ​
             //下标法  target[i] = source[i];
     ​
             i++;
         }
         //拷贝结束后,一定给target加上\0
         *(target + i) = '\0';
     ​
     ​
         return i;
     }
     ​
     ​
     int main(int argc,char *argv[])
     {
         //定义两个数组,从键盘录入字符串
         char source[20],target[20];
     ​
         printf("请输入一个字符串:\n");
     ​
         scanf("%s",source);
     ​
         //拷贝并复制长度
         int len = str_copy(source,target);
     ​
         printf("字符串:%s的长度是%d\n",target,len);
     ​
         return 0;
     }
     ​
案例2
  • 需求:字符指针作为函数的参数-给定一个字符串,截取start到end之间的字符串,含头不含尾

  • 代码:

     /*************************************************************************
       > File Name:    demo05.c
       > Author:       赵生鑫
       > Description:  
       > Created Time: 2025年03月20日 星期四 17时08分51秒
      ************************************************************************/
     ​
     #include <stdio.h>
     ​
     /*
      *定义一个函数,实现字符串的截取(含头不含尾)
      *@param source源字符串
      *@param start开始截取的位置(下标)
      *@param end结束截取的位置(下标)
      *@param target截取出来的字符串
      *@return target的串长
      *
      * */
     int str_substr(const char *source,int start,int end,char *target)
     {
         //定义循环变量(i时source取的下标,k时target存的下标)
         register int i = 0,k = 0;
     ​
         //遍历源字符串
         while(source[i] != '\0')
         {
             //根据start和end截取
             if(i >= start && i < end)
             {
                 //下标法target[k] = source[i];
                 *(target + k) = *(source + i);
                 k++;
             }
             i++;
         }
         //target截取结束,需要添加\0
         *(target + k) = '\0';
         return k;
     }
     ​
     ​
     int main(int argc,char *argv[])
     {
         char *str = "abcdefg";
         char target[26];
         int len = str_substr(str,2,5,target);
         printf("%s,%s,%d\n",str,target,len);
         return 0;
     }

##