C语言最常见的线性结构---数组

C语言最常见的线性结构—数组

数组详解

  • 数组定义:有序数据的集合,用数组名作为标识

  • 数组性质:数组是由一些列相同数据类型组成的线性集合

  • 数组组成:标识符、类型名、维数。其中,维数指定数组中的元素个数。

  • 数组优缺点:

    1)与vector类型相比,数组缺陷在于:数组的长度是固定的,不能知晓数组的长度。同时没有size和push_back操作。如果要更改长度,则要创建更大的新数组,再复制原数组的所有元素。

    :vector是C++中的STL容器的一个容器分支,属于动态数组内容

    2)数组是被严格限制在程序内部使用,只有当vector不能达到必要速度时,才使用数组。

    3)也正因为数组长度固定,所以根据数组位置访问是最快的。

一维数组

数组结构剖析

  • 所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。

在这里插入图片描述

  • 数组中的特定元素可以通过索引访问,第一个索引值为 0。

在这里插入图片描述

数组声明

  • 在 C 中要声明一个数组,需要指定元素的类型和元素的数量

    type arrayName [ arraySize ];

  • 这叫做一维数组。arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C 数据类型。例如,要声明一个类型为 double 的包含 10 个元素的数组 balance,声明语句

double balance[10];

此时一维数组就是一个名称为balance数据类型为double的数组,其含有10个元素大小的线性结构

### 数组初始化

- 在 C 中,您可以逐个初始化数组,也可以使用一个初始化语句,如下所示:

  ```c++
  double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
  • 大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目。

    如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,如果:

    double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    
  • 您将创建一个数组,它与前一个实例中所创建的数组是完全相同的。下面是一个为数组中某个元素赋值的实例

    balance[4] = 50.0;
    
  • 上述的语句把数组中第五个元素的值赋为 50.0。所有的数组都是以 0 作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去 1。以下是上面所讨论的数组的的图形表示:
    在这里插入图片描述

  • 下图是一个长度为 10 的数组,第一个元素的索引值为 0,第九个元素 runoob 的索引值为 8:

在这里插入图片描述

一维数组的深入

  • 由于C语言在计算机中是最贴切最底层逻辑的语言,所以C语言常被用来作为开发驱动型程序的语言和编译器底层结果的语言,由此来的现象是,C语言的数组会在编译过程中蜕化成为指针

    • 表面的的赋值方式:

    int num[10] = {0};//将数组初始化为0 num[0] = 5;//将数组的下标为0赋值为5;

    • 机器中C语言的真实赋值方式:

    `` int num[10] = {0};//将数组初始化为0
    *(num+0) = 5;//指针的方式将数组的下标为0赋值为5;`

二维数组

定义:

  • 数据类型 数组名 [ 行表达式][列表达式]

  • 由n行一维数组组成二维数组

  • 遵循行优先原则:

    int num[3][] = {1,2,3,4,5,6,7,8,9,10};//列可以省略,但是行不能省

  • 此外,与一维数组一样,定义数组时用到的“数组名[常量表达式][常量表式]”和引用数组元素时用到的“数组名[下标][下标]”是有区别的。前者是定义一个数组,以及该数组的维数和各维的大小。而后者仅仅是元素的下标,像坐标一样,对应一个具体的元素。

    C 语言对二维数组采用这样的定义方式,使得二维数组可被看作一种特殊的一维数组,即它的元素为一维数组。比如“int a[3 ][4];”可以看作有三个元素,每个元素都为一个长度为 4 的一维数组。而且 a[0]、a[2]、a[3] 分别是这三个一维数组的数组名。下面来验证一下看看是不是这么回事儿:

    # include <stdio.h>
    int main(void)
    {
        int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
        printf("%d\n", sizeof(a[0]));
        return 0;
    }
    

二维数组初始化

  • 分行给二维数组赋初值,比如上面程序的赋值方法:

  • 也可以将所有数据写在一个花括号内,按数组排列的顺序对各元素赋初值。比如:

    `int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};`
    

    效果与第 1 种是一样的。但第1种方法更好,一行对一行,界限清楚。第 2 种方法如果数据多,写成一大片,容易遗漏,也不易检查。

  • 也可以只对部分元素赋初值。比如:

    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  • 也可以只对部分元素赋初值。比如:

        int a[3][4] = {{1, 2}, {5}, {9}};
    
  • 它的作用是对第一行的前两个元素赋值、第二行和第三行的第一个元素赋值。其余元素自动为 0。初始化后数组各元素为:

    img

  • 如果在定义数组时就对全部元素赋初值,即完全初始化,则第一维的长度可以不指定,但第二维的长度不能省。比如:

        int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    
        int a[][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    
  • 系统会根据数据总数和第二维的长度算出第一维的长度。但这种省略的写法几乎不用,因为可读性差。

  • int a[3][4]={0};

    二维数组“清零”,里面每一个元素都是零。

二级指针开辟二维数组

  • 二级指针:存储指针的地址的变量(一级指针是存储变量的地址)

    arr[]==>(arr表示数组的首地址一定的元素类型的大小&arr
    表示整个数组的地址:移动的是整个数组的空间大小)
    二级指针(易混淆的内容,指针的地址数为4字节)
    
  • 二级指针蜕化操作:

      double a0 = 0;
      double *p0 = 0;
      double **s = &p0;
      s+1,*S+1,**S+1
      S+1 => S+sizeof(double8*)*1
      *s+1 => *s + sizeof(double)*1
      **s+1 => a0+1;s+1,
     (指针加一加4字节,;*s+1,double地址下一位,
     加8字节,;**s+1,0+1=1)
    
  • 二级指针开辟二维数组:

    a=1,b=2,c=3
    arr0[],arr1[],arr2[]
    int *p[4]={&a,&b,&c}
    int (*s)[4]={ar0,ar1,ar2}(4表示代表的是每一个一维数组的开辟的空间个数)
    *(*(s+2)+3) => *(s[2]+3) => s[2][3]
    

函数调用中的数组传参

函数中形参为数组的时候,用sizeof(数组名)时表示的是首地址的大小而不是整个数组的大小;形参中为二维数组的时候,如br[3][4]系统将退化成(*br)[4]

多维数组

其他的更高维数组总体原理类似于一维数组和二维数组
维数组的开辟的空间个数)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LredCoat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值