一维数组与二维数组———详细解读及一些注意事项

简介: 一维数组与二维数组———详细解读及一些注意事项

1.jpeg


目录



   一维数组

           一维数组的创建及初始化

           一维数组在内存中的存储

   二维数组

           二维数组的创建及初始化

           二维数组在内存中的存储

   数组越界

   数组注意事项

               1

               2

   二维数组主要应用:

       三子棋

       扫雷


一维数组


一维数组的创建及初始化


所谓数组,就是同一种元素的集合。一维数组的表达式为:


数组元素类型 +数组名+ [ 常量表达式];



#include<stdio.h>
int main()
{
  //元素类型为 int ,名为arr的共10个元素的数组
  int arr[10];
  //元素类型为 double ,名为arr1的共10个元素的数组
  double arr1[10];
  //元素类型为 char ,名为arr2的共10个元素的数组
  char arr2[10];
  //元素类型为 float ,名为arr3的共10个元素的数组
  float arr3[10];
  return 0;
}

 

这里注意一点,在C99标准里有变长数组的概念,所谓变长数组并不是指数组会变长,而是指用整型变量或表达式声明或定义的数组。如下所示:


int n=10;
int arr[n];


这里要注意的是,变长数组不能初始化,而且在一些编译器里使用变长数组,编译器会报错,比如在vs里就不能使用。


在创建数组的同时,给数组的内容一些合理值,这就是数组初始化。如下:


int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  //当不指定数组大小时,数组大小根据后面内容来确定
  int arr1[] = { 1,2,3,4,5 };
  //不完全初始化,只初始化数组前三个元素,其余为0;
  int arr2[10] = { 1,2,3 };
  //随机初始化
  int arr3[10];
  return 0;
}


2.png


这里我们还要知道,数组是使用下标来访问的,下标是从0开始。

一维数组在内存中的存储


看如下代码:


#include <stdio.h>
int main()
{
  int arr[10] = { 0 };
  int i = 0;
  //sizeof用来求数组大小,通常用如下表达式来求数组大小
  int sz = sizeof(arr) / sizeof(arr[0]);
  for (i = 0; i < sz; ++i)
  {
  //%p打印地址专用
  printf("&arr[%d] = %p\n", i, &arr[i]);
  }
  return 0;
}


3.png


这里我们可以看到,每一个数组后面的地址都会比前面大4,而我们知道,在32位环境下,一个地址就是32个二进制位,存储起来也就是32个比特位空间,即4个字节,也就是说,这些数组元素的地址随着下标的增长,是由低地址向高地址连续存放的!


4.png


二维数组


二维数组的创建及初始化


看下图:


#include<stdio.h>
int main()
{
  //3行4列,int类型,名为arr的二维数组
  int arr[3][4];
  //3行4列,char类型,名为arr1的二维数组
  char arr1[3][4];
  //3行4列,double类型,名为arr2的二维数组
  double arr2[3][4];
  return 0;
}


二维数组与一维数组相比较,多了行与列的区别。同样,我们也可以在创建数组的同时给数组内容赋合理的值,即二维数组初始化,大家看下图:


5.png


从这里我们可以看出,在二维数组初始化时,可以省略行,但不能省略列,同时,初始化的内容我们可以用{ }来限定。


同样,二维数组和一维数组一样,也是有下标的,从0行0列开始,如下:


6.png


二维数组在内存中的存储


与一维数组一样,我们看如下代码:


#include <stdio.h>
int main()
{
  int arr[3][4];
  //i控制行
  int i = 0;
  for (i = 0; i < 3; i++)
  {
  //j控制列
  int j = 0;
  for (j = 0; j < 4; j++)
  {
    //打印arr里每个元素的地址
    printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
  }
  }
  return 0;
}


7.png

我们可以看到,在32位机器里,二维数组与一维数组一样,每个数组元素的地址都要比前面那个元素多4字节,由此,我们可以看出,二维数组在内存中的存储依然是由低地址向高地址连续存放,如图所示:


8.png


数组越界



我们知道,数组都是通过下标来使用的,而下标又是有范围的,数组的下标从0开始,假如一共有n个元素,则下标最大为n-1。

而数组的下标一旦超过这个最大值,就会造成越界访问,所谓越界访问,就是超出合法空间访问,也就是超过了数组所在空间,就好像这样:


9.png


通过一段代码来验证:我们来看一下下面代码运行的结果:


#include<stdio.h>
int main()
{
  int arr[4] = { 1,2,3,4 };
  printf("%d", arr[4]);
  return 0;
}

 

10.png


我们可以看到,编译器并没有报错,但我们打印出来的值却不在我们可控范围内,这就是数组越界。


同样,二维数组也存在数组越界:


11.png


数组注意事项



1


我们要知道,数组名在作为参数时,传送的是数组首元素的地址,并不是整个数组:


#include<stdio.h>
int print(int arr[])
{
  return sizeof(arr) / sizeof(arr[0]);
}
int main()
{
  int arr[3] = { 1,2,3 };
  int tmp = print(arr);
  printf("%d", tmp);
  return 0;
}

 

有的人可能会说,打印的结果是3,但其实并非如此:

因为在这里,print(arr),这里的arr实际上是首元素,即arr[0]的地址,传送过去后,sizeof(arr)其实求的就是首元素的大小,即这里的sizeof(arr)就等价于sizeof(arr[0]),所以最终结果为1.


数组名表示首元素地址,但是,有两种情况是例外的,就是size

of(数组名),这里的数组名是表示整个数组。而我们上面的例子里,数组名arr先是作为参数传送的,所以传送过去的就是数组首元素的地址,所以求sizeof(arr)的时候,实际上求得是数组首元素的大小,注意分得清。


另外一种情况就是&数组名,这里表示的是取出整个数组的地址。这里的数组名表示整个数组。


除此之外,其余任何地方的数组名,都是表示数组首元素地址。

2


我们要注意数组中字符串类型的数组,具体看如下例题:


#include <stdio.h>
int main()
{
    char str[] = "hello boy";
    printf("%d %d\n", sizeof(str), strlen(str));
  return 0;
}


注意!:我们要知道,字符串结束的标志是\0,在这个数组里,实际上是有个\0的存在的,只不过被隐藏了,大家看下图所示:


12.png


而sizeof求的是数组所占内存空间的大小,char类型在

32位机器下,一个字符占用1个字节,这里加上\0一共是10个字符,所以一共是10*1=10个字节。

而strlen是专门用来求字符串长度的,\0不算在内,所以结果应该是9


13.png


同样,理清楚后,下面这道题也就很简单了:


14.png


acX实际上加上\0,一共8个字符,acY一共7个字符,并不等价

同样,在计算长度时,结束标志是\0,由于acY没有\0,所以长度随机值。


所以,正确答案为C。


二维数组主要应用:



三子棋与扫雷就运用到了二维数组,大家闲来无事可以写一下:


三子棋

扫雷


以上暂且讲到这,诸君加油。



相关文章
|
7月前
|
C语言
【C语言】利用数组处理批量数据(一维数组和二维数组)
【C语言】利用数组处理批量数据(一维数组和二维数组)
|
7月前
|
存储 C语言
二维数组的使用
这篇内容介绍了二维数组的概念,它是将一维数组作为元素构成的数组,也称为多维数组。文章详细讲解了如何创建二维数组,包括指定行数和列数,并展示了不同类型的初始化方式:不完全初始化(剩余元素设为0)和完全初始化。此外,还提到了按照行初始化的语法。内容中强调了C语言中二维数组的行和列都从0开始计数,并通过示例解释了如何访问和输出数组元素。最后,讨论了二维数组在内存中的存储方式,它是一维数组数组,元素在内存中是连续存放的。
78 0
|
7月前
|
存储 算法 搜索推荐
16二维数组
16二维数组
48 0
|
7月前
|
C语言
二维数组的知识
二维数组的知识
|
存储 算法 编译器
学C的第十二天【深入了解数组:一维和二维数组的创建和初始化;一维和二维数组的使用;一维和二维数组在内存中的存储;数组越界;数组作为函数参数;冒泡排序(对数组名的理解)】-2
5.二维数组的使用 操作符 [ ] :下标引用操作符,它其实就是数组访问的操作符,使用两个[ ],访问行和列 二维数组的行和列都是从0开始的
|
C语言
C语言中二维数组a[3][4]行列元素互换,存到另一个数组中。
C语言中二维数组a[3][4]行列元素互换,存到另一个数组中。
267 0
|
索引
labview数组数据一维数组二维数组索引行列元素替换子数组排序
labview数组数据一维数组二维数组索引行列元素替换子数组排序
271 0
二维数组的大小
int a[ 3 ] [ 4 ] 数组类型:int [ 3 ] [ 4 ],去掉变量名,就是变量的类型。这就是3行4列共12个int 类型元素的二维数组类型。
166 0
|
人工智能 编译器 C语言
二维数组
一、二维数组的定义 二、二维数组的访问 三、二维数组的初始化
二维数组