C语言11(数组指针与指针数组)

发布于:2024-12-18 ⋅ 阅读:(36) ⋅ 点赞:(0)

变量指针和指针变量

指针变量指向数组

通过指针引用数组元素

引用一个数组元素可以用:

①下标法:如a[i]形式

②指针法:如*(a+i)或者*(p+i),其中a是数组名,p是指向数组元素的指针变量,其初值:p = a;

案例

需求:有一整型数组a,有10个元素,输出数组中的全部元素

分析:要输出各元素的值,有三种方法

  • 下标法:通过改变下标输出所有元素
  • 指针法(地址):通过数组名计算出数组元素的地址,找出数组元素值==(不建议使用)==
#include <stdio.h>

void main()
{
    int arr[10];
    int i;
    //给数组元素赋值
    for(int i = 0;i < 10;i++)
    {
        scanf("%d",&arr[i]);
    }
    //遍历数组元素
    for(i = 0;i < 10;i++)
    {
        printf("%-4d",*(arr+i));
    }
    
    printf("\n");
}
  • 指针法(指针变量):用指针变量指向数组元素
#include <stdio.h>

void main()
{
    int arr[10];
    int i,*p;
    //给数组元素赋值
    for(int i = 0;i < 10;i++)
    {
        scanf("%d",&arr[i]);
    }
    //遍历数组元素
    for(p = arr;p< (arr+10);p++)
    {
        printf("%-4d",*p);
    }
    
    printf("\n");
}

以上三种写法比较:

  • 第一种写法与第二种写法执行效率相同。系统是将arr[i]转换为*(arr+i)处理的,即先计算出地址,因此比较费时

  • 第③种方法比第①②种方法快。用指针变量直接指向数组元素,不必每次都重建计算地址(p++)能大大提高执行效率

  • 用第一种写法比较直观,而用地址法或者指针变量的方法难以很快判断出当前处理的元素

使用指针变量指向数组元素时(上面第③种写法),注意以下三点:

*(p--)相当于arr[i--],先*p,再 p--

*(++p) 相当于arr[++i],先++p,再*

*(--p) 相当于arr[--i],先--p,再*

数组名作函数参数

表现形式:

1.形参和实参都是数组名

void fun(int[]  arr,int len){..}
void main()
{
 	int arr[] = {11,22,33};
    fun(arr,sizeof(arr)/sizeof(arr[0]));
}

2.实参用数组名,形参用指针变量

void fun(int *p,int len){..}
void main()
{
 	int arr[] = {11,22,33};
    fun(arr,sizeof(arr)/sizeof(arr[0]));
}

3.实参形参都用指针变量

void fun(int *p,int len);
void main()
{
 	int arr[] = {11,22,33};
    int *p = arr;
    fun(p,sizeof(arr)/sizeof(arr[0]));
}

4.实参为指针变量,形参为数组名

void fun(int arr[],int len);
void main()
{
 	int arr[] = {11,22,33};
    int *p = arr;
    fun(p,sizeof(arr)/sizeof(arr[0]));
}

案例

需求:将数组a中n个整数按相反顺序存放

#include <stdio.h>

/*
 *数组反转:数组实现
 *
*/


void  inv(int arr[],int len)
{
    //反转思路:将第0个和n-1个进行对调,将第1个和n-2个对调
    
    //定义循环变量
    int i = 0,temp;

    //遍历数组
    for(;i < len/2;i++)
    {
        // 交换
        temp = arr[i];
        arr[i] = arr[len - i -1];
        arr[len - 1 - i] = temp;

    }
}


/*
 *数组的反转:指针实现
 *const 给变量的数据类型前面加const,代表这个变量是只读变量,无法对此作出修改
*/

void inv2(int *p,const int len)
{
    //定义循环变量
    int *i = p, *j = &p[len -1],temp;

    //遍历数组
    for(;i < j;i++,j--)
    {
        temp = *i;
        *i = *j;
        *j = temp;
    }
    printf("\n");
}




/*
 *遍历数组
*/



void get(int arr[],int len)
{
    for(int i = 0;i < len;i++)
    {
        printf("%-3d",arr[i]);
    }
    printf("\n");
}


int main(int argc,char *argv[])
{
    int arr[] = {11,22,33,44,55,66};
    get(arr,sizeof(arr)/sizeof(arr[0]));
    inv(arr,sizeof(arr)/sizeof(arr[0]));
    get(arr,sizeof(arr)/sizeof(arr[0]));
    inv2(arr,sizeof(arr)/sizeof(arr[0]));
    get(arr,sizeof(arr)/sizeof(arr[0]));
    //执行遍历
    return 0;
}

数组指针与指针数组

数组指针

概念:数组指针是指向数组的指针(本质是指针)

特点:

  • 先有数组,后有指针
  • 它指向的是一个完整的数组

一维数组指针:

  • 语法:
数据类型(*指针变量名)[容量];
  • 案例:
#include <stdio.h>

/*
 *数组指针:指向数组的指针(这里不是指向数组元素的指针)
 *
*/

int main(int argc,char *argv[])
{
    //一唯数组指针
    //现有数组,再有指针
    int arr[] = {100,200,300};

    //获取数组的元素个数
    int len = sizeof(arr)/sizeof(arr[0]);

    //定义一个数组指针,指向arr这个数组
    int (*p)[3] = &arr; // &arr[0]等价 arr,此时p不是指向arr数组的第一个元素,而是指向arr这个数组本身

    //int *p = arr;//实际上指向了数组的第一个元素 

    //p++;//此时p++会跳出整个数组,访问到一块未知的内存,程序中尽量避免这种写法
    printf("%p\n",p);
    //如何访问数组指针
    printf("%d\n",(*p)[2]);

    //遍历
    for(int i = 0;i < len;i++)
    {
        printf("%d\n",(*p)[i]);
    }

    return 0;

}

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

二维数组指针:

  • 语法:
数据类型(*指针变量名)[行容量][列容量];
  • 案例:
#include <stdio.h>

int main(int argc,char *argv[])
{
    //创建一个普通的二维数组
    int arr[][3] = {10,20,30,100,200,300,1000,2000,3000};

    //创建一个二维数组指针
    //一个二维数组本质上还是一个一维数组,只不过它的元素也是数组
    int (*p)[][3] = &arr;

    printf("%d\n",(*p)[1][0]);

    //遍历
    for(int i = 0;i < sizeof(arr)/sizeof(arr[0]);i++)
    {
        int len = sizeof(arr[i])/sizeof(int);
        for(int j = 0;j < len;j++)
        {
            printf("%-4d",(*p)[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    return 0;
}

写法2:

#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建一个普通的二维数组
int arr[][3] = {10,20,30,100,200,300,1000,2000,3000};
// 创建一个二维数组指针
// 一个二维数组本质上还是一个一维数组,只不过它的元素也是数组
int (*p)[3] = arr; // 取二维数组的第一个元素 {10,20,30}
printf("%d\n",(*p)[0]);// 10
// 获取元素2000
printf("2000-%d,%d,%d",*(*(p+2)+1),*(p[2]+1),p[2][1]);// *(*(p+1)+2) 300
return 0;
}
  • 指针和数组中符号优先级:()>[]>*

  • 通过指针引用多维数组
    在这里插入图片描述
    案例1:

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

#include <stdio.h>

int main(int argc,char *argv[])
{
    //定义一个普通的二维数组
    int arr[3][4] = {1,3,5,7,9,11,13,15,17,19,21,23};

    //定义一个指针变量,用来接收二维数组的元素值
    int *p = arr[0];//&arr[0][0]
    
    //循环遍历
    for(;p < arr[0]+12;p++)
    {
        //每4个换行
        if((p - arr[0]) % 4 == 0)
        {
            printf("\n");
        }
        printf("%-4d",*p);
    }
    printf("\n");

    return 0;
}

在这里插入图片描述
案例2

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

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

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 r,c;

    //通过控制台来输入
    printf("请输入行号和列号: \n");
    scanf("%d,%d",&r,&c);

    printf("arr[%d][%d] = %d\n",r,c,*(*(p+r)+c));//*(*(p+r)+c) | *(p[r]+c) | p[r][c]
}




int main(int argc,char *argv[])
{
    arr_fun2();
    return 0;
}

在这里插入图片描述

指针数组

概念:指针数组是一个数组,数组中的每一个元素都是一个指针

特点:

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

语法:

数据类型 *数组名[容量];

int *arr[4]; int (*arr)[4]

案例:

#include <stdio.h>

int main(int argc,char *argv[])
{
    //定义三个变量
    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++)
    {
        printf("%-3d",*arr[i]);
    }
    printf("\n");

    return 0;
}

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到