C语言数组详解

本文详细介绍了C语言中一维数组和二维数组的创建、初始化方法,以及数组在内存中的存储方式。特别强调了数组名在函数参数中的含义,以及数组越界的问题。
摘要由CSDN通过智能技术生成

一维数组

创建和初始化

数组就是一组相同元素的集合。

他的创建:

char arr[10];
int arr1[5];

数组创建中 [] 里不能是变量,但是在c99标准之后就可以了被称为变长数组,但是不常用,而且变长数组不能初始化。

初始化:

//数组的初始化
int main()
{
	int arr[10] = { 1,2,3,4,5 };//不完全初始化,剩下的都是0
	int arr1[] = { 1,2,3,4 };
	int arr2[10] = { 0 };
	int arr3[] = { 0 };//这两种是不一样的初始化,arr2是十个元素,arr3是一个
}

创建数组的时候,如果不想指定 [] 的大小,就得初始化,数组的元素个数由初始化内容确认,例如:arr1,他的元素个数就是四个。

数组 arr 属于不完全初始化,但是他的元素个数还是10个,只不过剩下的初始化为0了。

arr2 和 arr3 要区分,他们的元素个数是不一样的。

一维数组的使用

//一维数组的使用
int main()
{
	int arr[10];
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
	for (int i = 0; i < sz ; i++)
	{
		arr[i] = i;
	}	
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

这个代码第一个循环我们可以自己初始化数组里的内容,第二个循环输出数组。我们用  sizeof(arr) / sizeof(arr[0]  可以来计算数组里有多少个元素。

总结:1.数组里的元素个数可以计算。

            2.数组使用下标来访问,下标从0开始。

一维数组在内存中的存储

//一维数组在内存中的存储
int main()
{
	int arr[10];
	int sz = sizeof(arr) / sizeof(arr[0]);
	//printf("%d\n", sz);
	for (int i = 0; i < sz ; i++)
	{
		arr[i] = i;
	}
	for (int i = 0; i < sz; i++)
	{
		printf("%p\n", &arr[i]);
	}
}//四个字节的存储因为是int类型   连续存储  随下标的增长地址从低到高

我们可以看到一维数组在内存中是连续存储的,而且每个地址都差四个,因为数组类型是 int ,int类型是四个字节的存储,每个字节都有一个地址,所以差四个。而且随下标的增长地址从低到高

二维数组

创建和初始化

创建:

char arr[2][3];
int arr1[3][4];

初始化:

int main()
{
	//      行 列
	int arr[2][3] = { {1,2,3},{4,5,6} };
	int arr1[2][3] = { 1,2,3,4,5,6 };//编译器会自己把他们分开
	int arr2[2][3] = { {1,2},{3,4} };//不完全初始化
	int arr3[][3] = { {1,2,3 }, {4, 5, 6} };//行可以省略,列不可以。
}

其实二维数组可以理解成几个一维数组的集合。我们可以调试看看他们存储的值:

看到 arr1 确实编译器给他分开了,二维数组的不完全初始化也会补0。

二维数组的使用

//二维数组的使用
int main()
{
	int arr[2][3] = { 1,2,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 2; i++)
	{
		int j = 0;
		for (j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
}

二维数组在内存中的存储

//二维数组内存中的存储
int main()
{
	int arr[2][3] = {1,2,3,4,5,6};
	int i = 0;
	for (i = 0; i < 2; i++)
	{
		int j = 0;
		for (j = 0; j < 3; j++)
		{
			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);//也是连续存储的,随下标的增长地址从低到高
		}
	}
}

可以看到二维数组和一维数组在内存中存储的方式一样,连续存储,差四个字节,随下标地址从低到高。

数组越界

int main()
{
	int arr[10];
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("数组里有%d个元素\n", sz);
	for (int i = 0; i < sz ; i++)
	{
		arr[i] = i;
	}	
	for (int i = 0; i <= sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

我就用一维数组的代码,做了修改,让 i <= sz ,这样 i  会等于 10 ,这样就数组越界了。

超出了数组合法空间的访问,但是编译器不报错,但是不代表代码就是正确的。所以使用时自己最好检查,二维数组也会越界。

数组名的不同意义

为了探讨数组名的意义,我们看一个冒泡排序的函数:(不知道冒泡排序可以关注我,我后面会讲解

//函数错误版本:数组传参的数组名是什么,是首元素的地址。
void sort(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[0]);//所以怎么计算sz都等于1.因为地址都是等于四个字节的
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
			}
		}
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	sort(arr);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}

我们需要把数组的元素从大到小打印出来,我们看看这个代码的结果:

他没有完成我们的任务,为什么会这样?

这样我们打印sz 的值看看

发现 sz是1,但是我们不是让他计算数组的元素个数吗,为什么会是1呢,就是因为我们函数传参的时候传的是数组名,这里的数组名代表的是数组的首元素地址,而地址的大小永远都是 4 /  8  

个字节。

所以我们正确的样子是:

//函数正确版本:
void sort(int arr[],int sz)
{
	//int sz = sizeof(arr) / sizeof(arr[0]);//给他换到主函数里
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
			}
		}
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	sort(arr,sz);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}

通过这个例子我们就发现数组名是首元素地址的意义。

当然有两个例外:1 . sizeof( 数组名 ) 这里计算的计算整个数组的大小

2. &数组名,这里也是取出的整个数组的地址。

但是整个数组的地址在数字上和首元素地址相同,给他们分别加1 就可以看出区别了:

int main()
{
	int arr[10];
	printf("%p\n", arr + 1);
	printf("%p\n", &arr[0] + 1);
	printf("%p\n", &arr + 1);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值