C语言 数组(批量处理数据)

一、谈谈你对数组的理解

     数组是一种构造数据类型。不同于指针,数组是在栈上静态分配空间,空间上是连续的,因为是静态分配空间,所以数组空间在定义时就分配空间,空间大小不能改变,造成空间利用率低的问题,为解决这一问题引入了可变长数组和柔性数组。数组按照维度可分为有一维数组、二维数组、三维数组等数组,数组的使用要注意 数组的定义、数组的初始化数组名数组地址所代表的的含义、数组名在当实参时,形参的类型,注意类型兼容问题。区分指针数组、数组指针、的使用和应用场景,最后还要区分指针和数组在空间分配、访问效率、安全性以及函数形参等方面的区别和联系。

二、如何使用数组

1、定义数组大小问题

C89标准:定义必须确定数组长度

        int a [100];

静态分配不灵活,怎么解决数组长度不灵活的问题———可变长数组(C99标准中)&柔性数组

(1)可变长数组

实现原理:用变量定义数组大小

C语言 数组(批量处理数据)_第1张图片

并不能真正解决数组长度问题 ,同时如果变量没有初始化,会随机赋值,当变量为负时,会出错

(2)柔性数组

C语言 数组(批量处理数据)_第2张图片

C语言 数组(批量处理数据)_第3张图片

2、一维数组         由元素组成,组成单位是元素

int a[];

a 指针常量,数组名不能自加自减,保存的是数组首元素地址,步长为单个元素步长
&a 对数组名取地址表示数组的地址,步长为整个数组元素所占大小的步长
*(&a) == a 对一维数组的地址取值等于数组首元素的地址

3、二维数组        可以看作由多个一维数组组成,组成单位是一维数组

int aa[][];

aa 指针常量,保存一维数组的地址
&aa 二维数组的地址
*(&aa)= aa 对二维数组的地址取值等于二维数组中首个一维数组的地址
*aa 二维数组中首个一维数组首个元素的地址

4、三维数组     可以看作由多个二维数组组成   

int aaa[2][2][2];

1、定义和初始化

C语言 数组(批量处理数据)_第4张图片

2、表达式说明:

aaa 三维数组名,指针常量,保存三维数组中首个二维数组地址
*aaa 首个二维数组中首个一维数组地址
**aaa 首个二维数组中首个一维数组首个元素地址
***aaa 首个二维数组中首个一维数组首个元素值
&aaa 三维数组地址
*(&aaa)=aaa 对三维数组地址取值等于首个二维数组的地址

5、 例: 分别用一维数组、二维数组、三维数组实现输入输出

#include
int main(int argc,char **argv)
{
    char a[100];
    printf("please input string\n");
    scanf("%s",a);
    printf("str1 = %s\n",a);

    int b[2][2];
    printf("please input number\n");
    for(int i = 0;i<2;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            scanf("%d",&b[i][j]);
        }
    }
     printf("输出结果为\n");
      for(int i = 0;i<2;i++)
    {
        for(int j = 0;j < 2;j++)
        {
            printf("b[%d][%d] = %d\n",i,j,b[i][j]);
        }
    }
    int c[2][2][2];
     printf("please input number\n");
     for(int i= 0;i<2;i++)
    {
        for(int j = 0;j<2;j++)
        {
            for(int k = 0;k<2;k++)
            {
                scanf("%d",&c[i][j][k]);
            }
        }
    }
     printf("输出结果为\n");
    for(int i= 0;i<2;i++)
    {
        for(int j = 0;j<2;j++)
        {
            for(int k = 0;k<2;k++)
            {
                printf("c[%d][%d][%d] = %d\n",i,j,k,*(*(*(c+i)+j)+k));
            }
        }
    }
}

C语言 数组(批量处理数据)_第5张图片

C语言 数组(批量处理数据)_第6张图片

5、指针数组

        char *pa[3]

        数组中保存的元素都是指针

1、注意:        

        a\没有被初始化的数组指针都是野指针,使用方法和指针一样,使用时要分配空间,使用完了要及时释放空间并置空

        b\函数传参时,传递一维数组指针名,形参要用二维指针,因为传递一维数组名,用一维数组元素类型的指针,数组中的元素是指针,指针的指针是二维指针。

例:指针数组的定义和传参

#include

void print4(char **pa)
//注意是二维指针,传递数组名,形参是数组类型的指针,数组元素类型是指针,指针的指针不就是二维指针了吗
{
    for(int i = 0;i<3;i++)
    {
        printf("pa[%d] = %s\n",i,pa[i]);
    }

}
int main()
{
    char *pa[3] ={"hello1","hello2","hello3"};
    print4(pa);
}

C语言 数组(批量处理数据)_第7张图片

6、数组指针

 1、概念

      数组的地址用数组指针变量保存,或者说指针指向数组首元素地址

 2、如何定义

     int  (* pa)  [3];== int a[3];

     pa == &a; *p == a;

注意:可以把 * 和 &看作 互为逆运算

 3、数组指针使用场景——函数传参
 

#include
void print1(char *p)
{
    printf("str1 = %s\n",p);
    return;
}
void print2(char (*p)[100])
{
       for(int i = 0;i<2;i++)
    {       
        printf("str[%d] = %s\n",i,p[i]);//*(p + i)
    }
    return;
}
void print3(char (*p)[2][100])
{
     for(int i= 0;i<2;i++)
    {
        for(int j = 0;j<2;j++)
        {
           printf("%s\n",p[i][j]);//*(*(p+i)+j)
        }
    }
    return;
}
int main(int argc,char **argv)
{
    char a[100];
    printf("please input string\n");
    scanf("%s",a);
    print1(a);

    char b[2][100];
    printf("please input string\n");
    for(int i = 0;i<2;i++)
    {
       scanf("%s",b[i]);//*(b + i)
    }
     printf("输出结果为\n");
     print2(b);

    char c[2][2][100];
     printf("please input string\n");
     for(int i= 0;i<2;i++)
    {
        for(int j = 0;j<2;j++)
        {
           scanf("%s",c[i][j]);//*(*(c+i)+j)
        }
    }
     printf("输出结果为\n");
     print3(c);

    return 0;
}

C语言 数组(批量处理数据)_第8张图片       

        (1)传递实参为一维数组名,形参用用元素类型的指针接

               a为一维字符数组名,print1为调用函数名

               实参: print1(a)形参:void print1(char * str) 

        (2)传递实参为二维数组名,形参用一维数组指针接(相当于二维指针)

                 print2(aa)                        char (*a)[]

        (3)传递实参为三维数组名,实参用二维数组指针接(相当于三维指针)

                 print2(aaa)                      char (*a)[][]

补:  数组在做形参时,编译器会把数组会退化成指针,这样能提高效率

        1、一维数组回退化成一维数组元素类型指针(一维指针);2、二维数组会退化成指向一维数组的指针(二维指针);3、三维数组回退化成指向二维数组元素的指针(三维指针)

指针数组与数组指针详解_men_wen的博客-CSDN博客_指针数组

三、指针与数组区别

1、空间大小

        数组是静态分配空间(栈),空间是连续的,定义即分配空间,访问效率快,存在空间长度固定的问题,不能更改,易产生空间利用率低,造成空间浪费。指针则是动态分配,用链表实现,空间长度可根据需求改变需要用户人为分配空间(堆上),使用完要及时释放空间,防止内存泄漏。

2、访问效率

        数组连续访问快,指针灵活性好,用来随机访问数据

3、安全性

        数组有系统管理空间,安全性好,指针空间是用户管理,需要自己分配、释放,容易造成内存泄漏,安全性差。

4、函数形参(类型兼容问题)

        数组在做形参时,编译器会把数组会退化成指针,这样能提高效率

        1、一维数组回退化成一维数组元素类型指针(一维指针);2、二维数组会退化成指向一维数组的指针(二维指针);3、三维数组回退化成指向二维数组元素的指针(三维指针)

https://hanshuliang.blog.csdn.net/article/details/121637890

四、指针与数组的复杂声明(待补充)

你可能感兴趣的:(C语言基础,vscode,linux)