数组详解(含二维数组)

20 篇文章 0 订阅
17 篇文章 0 订阅

数组定义
一组相同类型的元素集合
定义模板
在这里插入图片描述比如

int arr[10] = {10};

注:c99中引入了变长数组的概念,允许数组的大小可以用变量来指定,所以c99支持的编译器中

int n = 10;
int arr[n] = {0};

这样定义的就是变长数组。但是VS是不支持c99的,所以在VS中是不能定义变长数组的。
同时变长数组并不是说数组创建后可大可小,而是只一开始创建时,长度n可以由变量指定。

数组的初始化
在创建数组的时候同时给一些元素赋值就是数组初始化。
如果不我们不人为初始化,创建系统也会默认初始化各元素为0

int arr[10] = {0}//第一个元素人为初始化为0,后面九个元素是系统默认初始化为0 
int arr[10] = {1,2,3,4}//前四个元素初始化为1234,后面初始化为0

在这里插入图片描述在这里插入图片描述

一些不常见的初始化形式

char arr[] = {'a','b','c'};//初始化的时候可以不人为指定数组大小,此时系统会根据后面的赋值的元素个数来确定数组的大小
char arr[] = {'a',98};//字符型数组里面元素是整型常量会自动转化成对应的ASCII码字符

在这里插入图片描述在这里插入图片描述

注意:如果我们一个元素都不初始化

int arr[10]

这样是违规的,系统也不会把10个元素默认赋值为0,在VS中这样写过后实际上赋10个随机值,一旦我们人为赋值了第一个元素,系统就认为我们初始化了,所以剩下的我们没有人为赋值的元素也会赋值为0;
在这里插入图片描述注:如果是全局变量,在创建的时候我们不初始化,系统会默认赋值为0,静态变量也是。
在这里插入图片描述在这里插入图片描述

这两个之所以会和数组不同是因为不同数据在内存中实际存放的位置不同
在这里插入图片描述
局部变量和形参会存放在内存的栈区,栈区里所有变量在系统默认初始化时会初始化为随机值
而全局变量、静态变量存放在静态区,系统在默认初始化时是初始化为0;

初始化字符数组
下面是两种字符数组的初始化

char arr1 =['a''b','c'];
char arr2 = "abc";

在这里插入图片描述这两种初始化是不同的,后者实际是四个元素,是一个字符串,多一个\0。所以对这两个数组使用sizeof()和strlen()都会不一样。详情可以去看我另外一篇博客。

字符数组初始化系统默认初始化是赋值成\0
在这里插入图片描述
数组的访问

数组可以通过下标访问,下标从0 开始,对应首元素。

int arr[] = {1,2,3,4};//创建加初始化
int n = arr[0]//n等于1

[ ]这个方括号在C中叫下标引用操作符,有两个操作数,一个是数组名arr,一个是数组元素下标0。

计算一个数组的大小

int length = sizeof(arr)/sizeof(arr[0]);//length的值等于数组元素的个数,sizeof(arr),是整个数组的大小

一维数组在内存中存储

在这里插入图片描述1.数组元素在内存中是连续存放的
2.每个元素地址正好差一个整型元素的大小(4个字节)。
3.随着下标增长,地址是由低到高变化的。

数组的步长
在这里插入图片描述数组的步长是也是一个元素的大小,比如整型就是4个字节。

二维数组

二维数组的初始化
一维数组一样,系统默认初始化为0,字符数组就是\0

int main()
{
	int arr1[3][5] = { 1,2,3,4,5,6 };//这种就和一维数组一样
	int arr2[3][5] = { {1,2 }, {3, 4 }, {5, 6} };
}

在这里插入图片描述前一种123456分别在第一行第一列,第一行第二列…先行后列的排布。
后一种可以这样理解,将{1,2}看做一个元素,其他两组也是一样,这样实际就是一维数组。所以也就是12按顺序放在第一行,34放在第二行,56放在第三行。
但是
注意的是二维数组的初始化是不允许列数为空的。

int arr[][2] = {1,2,3,3,4,5};//这样是可以的,行数系统可以根据元素个数自行安排
int arr[2][] = {1,2,3,3,4,5};//这样不可以

二维数组的访问

int main()
{
	int arr1[3][5] = { 1,2,3,4,5,6 };![在这里插入图片描述](https://img-blog.csdnimg.cn/5115373e75264aae90f20f563637c97c.png)

	int i = 3;
	int j = 5;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr1[i][j]);
		}
		printf("\n");
	}
}

在这里插入图片描述

计算二维数组一行的大小,一列的大小,整个数组的大小

int main()
{
	int arr[3][5] = { 1,2,3,4,5,6 };
	int hang_length = sizeof(arr) / sizeof(arr[5]);//一行共有几个元素
	int lie_length = sizeof(arr) / sizeof(arr[3]);//一列共有几个元素
	int length = sizeof(arr) / sizeof(arr[0][0]);//二维数组有几个元素
}

二维数组在内存中的存储
在这里插入图片描述1.先行后列连续存储
2.两个元素地址差值正好是4,也就是一个整型变量的大小4个字节
在这里插入图片描述

数组传参问题

可以去看我的另外一篇博客,说的就是这个问题
https://blog.csdn.net/baixian110/article/details/130140513?spm=1001.2014.3001.5501
也可以直接看这里,我在写一遍,正好熟悉一下冒泡排序

void swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}
void bubble_sort(int arr[])
{
	int length = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int j = 0;
	for (i = 0; i < (length - 1); i++)//元素个数为length,则冒泡排序的趟数是length-1
	{
		for (j = 0; j < length - 1 - i; j++)//每一趟是length - 1 - i次比较
		{
			if (arr[j] < arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);//如果前面一个数小于后面一个数,就交换。
			}
		}

	}

}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 ,10 };

	int i = 0;
	bubble_sort(arr);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);

	}
}

这个代码结果是
在这里插入图片描述
并没有实现由大到小排序。
我们监视去看length的值就会发现,length的值并不是数组长度10,而是1,这是因为在数组传参时
bubble_sort(arr)中arr表示的首元素的地址,虽然与数组其实地址是相同的,但是在bubble_sort中形参 arr[]实际只有一个元素,因为只传了一个元素过来,所以bubble_sort函数里面sizeof(arr)的返回值是1.

所以正确的代码是

void swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}
void bubble_sort(int arr[], int length)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < (length - 1); i++)//元素个数为length,则冒泡排序的趟数是length-1
	{
		for (j = 0; j < length - 1 - i; j++)//每一趟是length - 1 - i次比较
		{
			if (arr[j] < arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);//如果前面一个数小于后面一个数,就交换。
			}
		}

	}

}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 ,10 };
	int length = sizeof(arr) / sizeof(arr[0]);//把length值放在主函数里面求
	int i = 0;
	bubble_sort(arr, length);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}

事实上数组名作为指针一般指向的都是首元素,也就是说arr一般是首元素地址,只有两种情况指向的是整个数组
一种是sizeof(数组名),这里数组名代表整个数组,所以sizeof(arr)的值是整个数组的内存大小(字节为单位)
一种是&数组名,这里表示的是取的是整个数组的地址,虽然在数值上和首元素地址地址没区别,但是步长有根本区别,可以看后面的代码

下面我们来看下面的代码就能更加明白一点

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 ,10 };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr[0]));
	printf("\n]");
	printf("%p\n", arr);
	printf("%p\n", arr + 1);
	printf("\n");
	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0] + 1);
	printf("\n");
	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);
}

结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/8669fdb4a14b4320a479f4eeacf3bfd0.png在这里插入图片描述

arr表示除两种情况均表示的是首元素的地址,所以步长是4,所以第一个和第二个差值也是4
&arr[0]表示取首元素地址,那么步长还是4。
&arr表示取数组地址,那么步长就是数组大小,40.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值