C语言-数组


前言

浅谈数组

一、数组如何初始化

这里我将 数组的初始化方式举例(一维数组):
int arr1[10] = {1,2,3};
这样创建出来的数组是这样的
在这里插入图片描述
它将1,2,3赋给前面三个空间后,后面七个空间自动赋值为0;

int arr2[] = {1,2,3,4};
赋值结果为
在这里插入图片描述
这里我们可以看出,这样赋值得到的是通过后面我们给出的值而分配的数组长度。我们只给了四个值,那么数组就只分配了四个空间。

char arr6[] = “abcdef”;
赋值结果为
在这里插入图片描述
我们可以看到这样赋值数组会自动将字符一个一个拆开放入数组中,并且会在最后一个字符后面再放入一个’\0‘,这个字符是数组结束的标志。
ps:字符\0与数字0是不一样的,字符\0的ASCII码值是0,而0的ASCII码值不为0

二、一维数组的操作符"[]"

“[]”是下标引用操作符,它的作用是访问数组的元素
例如:arr[4]就是访问数组下标为4的元素,数组下标用0开始编号,下标为4,即为第5个元素。

三、数组大小的计算

int arr[10]
int sz = sizeof(arr)/sizeof(arr[0]);

这段代码通过先计算数组的总字节数,再除以一个元素的所占字节数,就得到了数组的大小。

四、一维数组在内存中的存储

数组在地址中是连续存放的。以int arr[4]为例子
若首元素地址为x,则&arr[1]的地址即为x+4;因为一个int型的大小为4,故地址要往后移动4个字节,若为char,则往后移动一个字节

代码示例:

#include<stdio.h>
int main()
{
	int arr[4] = { 1,3,5,6 };
	for (int i = 0; i < 4; i++)
	{
		printf("%p \n", &arr[i]);
	}
	return 0;
}

这段代码的作用是打印出各个数组元素的地址,执行结果如下
在这里插入图片描述
我们可以看到第一个元素的地址要比第二个元素地址少4,第二个元素地址要比三个元素地址少4.如此我们可以推断出,数组元素的地址是由低到高的

五、二维数组的创建和初始化

二维数组是一维数组的更高一个维度,下面是二维数组创建的实例
int a[3][4] = {1,2,3,4};
int a[3][4] = {{1,2},{3,4}};
int a[][4] = {1,2,3,4,5};//给二维数组赋值时,可以省略第一个方括号里的值。其原因后面解释

六、二维数组在内存中的存储

代码示例:

#include<stdio.h>
int main()
{
	int a[3][3];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%p\n", &a[i][j]);
		}
	}
	return 0;
}

我们通过这段代码对二维数组的每一个元素的地址进行打印。
打印结果:

在这里插入图片描述
我们可以清晰的看到每一个元素的地址都是前一个元素的地址加4;
如此我们可以推断出虽然二维数组叫二维,但在内存存储中仍然是一维的,与一维数组的存储相差无几

七、数组访问越界

这个其实非常好理解,比如你创建了int arr[3]的数组,你却要访问arr[4],这在原本初始化数组的时候就没有为其分配第5个元素的地址,只有3个元素的地址,这就是数组访问越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查

八、数组初始化的特殊样式

前面我们说过 ‘[ ]’ 是一个操作符,我们以操作符的角度去理解它,我们以 ‘+’ 号为例:
3+4 我们可以写成 4+3;而int a[3] 我们也可以写成 int 4[a];
这样我们可以得到一种新的初始化方式:

int 4[a] = {1,2,3,4};

这样看起来非常奇怪,但是它是正确的:

同时我们上面提到二维数组赋值的时候可以忽略掉第一个括号里的数字,而不能忽略掉第二个括号里的数字,原因是,第二个括号里的数字决定的是列数,如果把列数忽略了,当你在赋值时,数组不知道何时开始给第二行的数组赋值,这样数组的大小就不确定,自然而然列数就必须确定。但是行数不一样,当列数确定时,行数可以由赋值的个数来决定。这样赋值出来的数组的大小也是确定的

九、数组名是什么?

我们在日常的代码中经常能看到数组名作为参数,
例如:函数传参的时候,将数组传进去传的是数组名
那么数组名到底是什么呢?
实际上,数组名代表的是数组的首地址,也就是说,函数传参时,传的数组名其实是数组的首元素地址,但是这里有两个特殊的地方:

一、sizeof(arr)
二、&arr

第一个情况:sizeof(arr);为什么特殊呢,我们想一想,若arr为首元素的地址,那为什么sizeof(arr)算的是整个数组所占的字节数呢。实际情况确实如此,arr确实为首元素的地址,但是算的是整个数组的长度。所以将它列为特殊情况
第二个情况:&arr;那么这个为什么特殊呢,我们来看一段代码

#include<stdio.h>
int main()
{
	int arr[3] = { 1,2,3 };
	printf("arr[0]的地址为%p\n", &arr[0]);
	printf("arr[0]+1的地址为%p\n", &arr[0]+1);
	printf("arr的地址为%p\n", &arr);
	printf("arr+1的地址为%p\n", &arr+1);
	return 0;
}

这段代码的作用是打印arr[0]的地址及其+1的地址,和arr的地址及其+1的地址,打印结果如下
在这里插入图片描述

我们可以看到,虽然&arr[0]的地址和&arr的地址一样,但arr[0]+1的地址为arr[0]的的地址加4,即一个整型,但&arr+1的地址为&arr的地址加12,即三个整型,也就是说,&arr+1是向后跳整个数组,而&arr[0]是向后跳一个整型;

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dontflinch

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

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

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

打赏作者

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

抵扣说明:

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

余额充值