首页 > 其他分享 > 一维数组与二维数组———详细解读及一些注意事项

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

时间:2023-02-13 21:33:05浏览次数:51  
标签:10 arr 数组 int 元素 一维 注意事项 sizeof


一维数组

一维数组的创建及初始化

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

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

#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;
}

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


这里我们还要知道,数组是使用下标来访问的,下标是从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;
}

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


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

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

二维数组

二维数组的创建及初始化

看下图:

#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;
}

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

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


从这里我们可以看出,在二维数组初始化时,可以省略行,但不能省略列,同时,初始化的内容我们可以用{ }来限定。同样,二维数组和一维数组一样,也是有下标的,从0行0列开始,如下:

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

二维数组在内存中的存储

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

#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;
}

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


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

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

数组越界

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

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

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


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

#include<stdio.h>

int main()
{
int arr[4] = { 1,2,3,4 };


printf("%d", arr[4]);
return 0;
}

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


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

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

数组注意事项

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的存在的,只不过被隐藏了,大家看下图所示:

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

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

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

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

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


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

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


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

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

所以,正确答案为C。

标签:10,arr,数组,int,元素,一维,注意事项,sizeof
From: https://blog.51cto.com/u_15954929/6054716

相关文章

  • 数组的排序和查找
    1.数组156注意数组知识点double[]hens={3,5,1,3.4,2,50};1.double[]表示是double类型的数组,数组名hens2.{3,5,1,3.4,2,50}表示数组的值/元素,依次表示数......
  • *(*(p + 2) + 1) 二维数组指针位移
    ......
  • nvm的使用与注意事项
    注意事项:    1、不能安装任何node版本(如存在请一定删除后安装nvm);Node卸载超详细步骤1、打开系统的控制面板,点击卸载程序,卸载nodejs      2、删......
  • JavaScript 数组求交集
    letarr1=[1,2,3,4,5];letarr2=[4,5,6,7,8];//数组求交集functionarrayIntersection(arr1,arr2){//先去重letarr1Unique=[...newSet(arr1)];......
  • java数组基础
    数组初始化就是给数组元素分配内存,并为每个元素赋初始值。初始化数组有两种方式:静态初始化(事先知道数组里存储那些数据)int[]c=newint[]{1,2,3,4,5,6};动态初始化......
  • 【LeeCode】581. 最短无序连续子数组
    LeeCode【题目描述】给你一个整数数组 ​​nums​​ ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。请你找出符合题意的 最......
  • #yyds干货盘点# LeetCode程序员面试金典:合并排序的数组
    题目:给定两个排序后的数组A和B,其中A的末端有足够的缓冲空间容纳B。编写一个方法,将B合并入A并排序。初始化 A和B的元素数量分别为 m和n。示例:输入:A=[1......
  • reduce(累加器)数组去重
    letarr=[{id:1,name:'张三',hobby:"抽烟,喝酒,烫头"},{id:2,name:'李四',hobby......
  • 记录--数组去重的五种方法
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言您或许会疑惑,网上那么多去重方法,这篇文章还有什么意义?别着急,这篇文章只节选了简单的,好玩的,古老的,有......
  • 操作数组对象中的某个属性获得一个新的数组对象
    letarr=[{name:'张三',hobby:"抽烟,喝酒,烫头"},{name:'李四',hobby:"打麻将,蹦迪,烫头"}......