---数组---

一维数组的创建和初始化

数组的创建

在存储数据时少量数据可以直接定义普通变量,但是遇到大量的同类型数据时用普通变量就不行了,这就用到了数组。

数组 - 一组相同类型元素的集合

数组的创建方式:
type_t arr_name [const_n];

  • type_t 是指数组的元素类型
  • const_n 是一个常量表达式,用来指定数组的大小

例子:
int arr[10];
char ch[10];
double data1[20]
double data2[15+5];
下面的代码只能在支持C99标准的编译器上编译
int n = 10;
int arr2[n];
在C99标准之前,数组的大小必须是常量或者常量表达式,在C99之后,数组的大小可以是变量,为了支持变长数组。

数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
在未进行初始化的时候数组内部是随机值。
例子:
int arr1[10]={1,2,3};//不完全初始化,剩余的元素默认初始化为0
int arr2[10]={1,2,3,4,5,6,7,8,9,10};//完全初始化。
int arr3[] = { 1,2,3 };//数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
char str1[10]={‘a’,‘b’,‘c’};//内部元素abc’\0’‘\0’‘\0’‘\0’‘\0’‘\0’‘\0’
char str2[10]=“abc”;//内部元素abc’\0’‘\0’‘\0’‘\0’‘\0’‘\0’‘\0’
上面的str1和str2虽然数组内容一样,但是str1是存放abc后剩余元素默认为0,str2是存放abc’\0’后剩余元素默认为0;
char ch1[]=“abc”;//内部元素abc’\0’
char ch2[3]={‘a’,‘b’,‘c’};//内部元素abc

一维数组的使用

在数组中的元素都是顺序存储的,每个元素都有自己的编号,编号从0开始,这个编号就叫做下标,通过下标来访问数组中的元素我们必须了解一个操作符,那就是 [] - 下标引用操作符,通过下标和下标引用操作符以及数组,就可以访问数组中任何一个元素了。

例子:

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	arr[4] = 50;//对下标为四(也就是第五个元素进行修改)
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的大小
	int i = 0;
	for (i = 0; i < sz; i++)//对数组中所有元素进行遍历输出
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

一维数组在内存中的存储

一维数组在内存中是连续存放的,下面让我们来证明

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的大小
	int i = 0;
	for (i = 0; i < sz; i++)//对数组中所有元素的地址进行遍历输出
	{
		printf("%p\n", &arr[i]);
	}
	return 0;
}

在这里插入图片描述

上图白色的是程序输出结果,是数组在内存中存放的地址。每个地址相差4也就是一个整形变量的大小所以说明了数组元素是连续存放的,并且是从低地址到高地址存放,

二维数组的创建和初始化

在具有相同性质的元素对其进行分组时,分的几组数据无法用一维数组进行存储,那我们就得用二维数组了

二维数组的创建

二维数组的创建和一维数组有很多相似的地方,就是多了个[],都是存储相同数据类型的元素,相同数据类型可以是int char float……
例子:
int arr[3][4];
char ch[3][4];
double arr2[3][4];

二维数组的初始化

int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};//完全初始化,

int arr2[3][4] = {1,2,3,4,5,6,7,8,9};//最后几个都是默认为0,我们把二维数组第一个下标看作行下表,第二个看作列下标。
在这里插入图片描述

int arr3[3][4] = {{1,2},{3,4},{5,6}};\在每一列中未被初始化的默认为0
在这里插入图片描述
int arr4[][4] = { 1,2,3,4,5,6};//二维数组只能省略行,不能省略列;具体缘由在下面二维数组的存储再解释

二维数组的使用

二维数组的使用和一维数组很相似都是通过数组名和数组[]以及下标来访问。

对二维数组某数据进行改变,并且遍历输出二维数组

#include<stdio.h>
int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	arr[2][0] = 9;//对第二行第零列赋值为9
	int i = 0;
	for (i = 0; i < 3; i++)//对二维数组进行遍历
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

二维数组在内存中的存储

二维数组是如何进行存储呢?是所有元素连续存储,还是其他存储方式呢,下面我们用类似于一维数组对其地址进行输出来证明二维数组是何种存储方式。

#include<stdio.h>
int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	int i = 0;
	for (i = 0; i < 3; i++)//对二维数组的地址进行遍历输出
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("&arr[%d][%d] = %p\n", i,j,&arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果
在这里插入图片描述
同一行中每一个元素相差4,上一行的最后一个与下一行的第0个相差四,相差的都是整形数据的大小,所以证明了二维数组所有数据都是在来连续存储的,并且是由低地址到高地址。
在这里插入图片描述

由二维数组的存储可知,必须由列的大小。
比如:int arr[][4]={1,2,3,4,5,6};
这个二维数组可以唯一确定数组存储的方式,列数为4,行数为2,未初始化赋值的就默认为0,但是没有列数int arr[][];或者int arr[2][];都不能唯一确定二维数组的存储方式

数组越界

数组是存储在内存空间上具有一定的大小,由下标进行访问,数组的下标是有范围限制的。数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

越界访问错误示范:
在这里插入图片描述

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查。

错误示范改正

#include<stdio.h>
int main()
{
	int arr[6] = { 1,2,3,4,5,6 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

用sizeof求数组的大小,这样可以减少数组最后元素位置找错,但是不能避免毕竟一个人想写bug谁也拦不住

数组作为函数参数

一般我们会把数组作为参数进行函数的传参,形参呢有两种形式,接下来通过冒泡排序来举例说明

冒泡排序:
对一组数据进行升序排序(ex: 9,8,7,6,5,4,3,2,1,0)
冒泡排序的核心思想是相邻两个进行比较
在这里插入图片描述

上图经过了九次比较找出了一个最大的,接下来最后一个是最大的不用再进行比较,再进行8次比较就可以找到第二大了,一趟冒泡排序找出一个最大的,一共进行八趟冒泡排序就可以将整租数据正序排列
在这里插入图片描述

数组传参时有两种形式:1.数组,2。指针

冒泡排序形参以数组的形式进行设计

#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j= 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

冒泡排序形参以数组的形式进行设计

void bubble_sort(int *arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j= 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

有的同学就会有疑问,那么形参以数组的形式进行设计中sz在冒泡排序函数内部可以吗?
答案是不可以的,别看int arr[]看起来像数组其实就是一个指针,不能在函数内部进行设计,接下来来介绍数组名

数组名是什么?

一维数组名的理解

数组名其实就是数组首元素的地址,但是我们经常用的sizoef (数组名)求的却是整个数组的大小呢?
原因是数组名有两个特例,数组名代表整个数组的地址,

  • sizeof(数组名)
  • &数组名

那么&数组名代表的整个数组的地址和数组名代表着数组首元素的地址有什么区别呢。
在这里插入图片描述

第一组和第二组证明了数组名是数组首元素的地址,+1跳过的是4个字节也就是一个元素的大小,
第三组中+1直接跳过四十个字节,也是整个数组。

二维数组的数组名的理解

二维数组可以看作是一维数组的数组,
例如:arr[3][4];

  • arr[0]//可以看作是大小为4的一维数组,arr[0],也是代表着一维数组名。&arr[0]+1跳过的也是整个一维数组的大小,也就是跳过二维数组的一行。
  • 用sizeof可以求出二维数组行数和列数。
#include<stdio.h>
int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	printf("%p\n", &arr);
	printf("%p\n\n", &arr + 1);//二维数组名代表首元素的地址,跳过整个数组

	printf("%p\n", &arr[0]);
	printf("%p\n\n", &arr[0]+1);//跳过一行元素。

	printf("%d\n\n", sizeof(arr));//整个数组所占空间的大小
	
	printf("%d\n", sizeof(arr) / sizeof(arr[0]));//数组的行数
	printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));//数组的列数

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值