数组初步了解(1)

发布于:2022-11-08 ⋅ 阅读:(1209) ⋅ 点赞:(1)

目录

1.一维数组

1.1一维数组的使用

1.2一维数组的存储 

2.二维数组

2.1二维数组的使用

2.2二维数组的存储

3.数组越界

4.数组作为函数参数

4.1冒泡排序

// 对一组整数升序(从小到大)排列

 4.2数组名


1.一维数组

1.1一维数组的使用

定义:数组是一组相同类型元素的集合

形式:type_t类型   arr_name名字     [const_n]个数

 例 :      int  arr [10]  ;int  arr2 [5+6]

在C99标准之前,[ ]中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。不同编译器情况不同。

在VS编译器里,[ ] 中只能放常量不能放变量。

不完全初始化时,剩余元素默认初始化为0;

没有指定数组元素个数,编译器会根据初始化的内容来确定数组的元素个数;

数组时使用下标来访问的,下标从0开始,[ ]下标引用操作符;

数组大小:int  sz  =  sizeof ( arr ) / sizeof ( arr [0] ); 

1.2一维数组的存储 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[10] = { 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("&arr[%d]= %p\n", i, &arr[i]);//注意这里不是数组名arr,而是确切的数 
                                             //组中的元素arr[i],所以要加&
	}
	return 0;                              
}

 ​​

观察上述运行结果可知:

地址是以16进制打印的(二进制太长了)且每两个地址之间差值为4,这正好对应了int占用4个字节。

 

一维数组在内存中是连续存放的

随着数组下标的增长,地址是由低到高变化的

 那么我们只要知道第一个元素的地址就可打印出所有元素:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int* p = &arr[0];//找到第一个数组元素的地址
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//就可以找到其他元素
	}
	return 0;
}

 

 是不是很神奇?觉得不可思议?没关系,我们再来验证一下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int* p = &arr[0];
	for (i = 0; i < sz; i++)
	{
		printf("%p——%p\n", p + i, &arr[i]);
	}
	return 0;
}

 结果依旧如此~

2.二维数组

2.1二维数组的使用

int  arr [3][4]          3行4列    12个元素

double  arr[4][5]    4行5列    20个元素

先放行再放列;

行可以省略,但是列不能省略;

行和列都是从零开始的。

int main()
{
	int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	int arr2[3][4] = { 1,2,3,4,5 };
	int arr3[3][4] = { {1,2},{3,4},{5,6} };//第一行放1,2;第二行放3,4
                                           //第三行放5,6,其他未初始化的默认为0。
    int arr4[ ][4] = {1,2,3,4,5,6,7,8,9 };//行可省略列不能省略,结果是第一行1,2,           
                                          //3,4,第二行5,6,7,8,第三行9。
    int arr5[ ][2] = {1,2,3,4,5,6,7,8,9 };//此时行数发生变化,自动适应个数,结果
                                          //为5行2列。
}                                          

2.2二维数组的存储

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	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]);
		}
	}
	return 0;
}

 分析上述运行结果可知,二维数组在内存中也是连续存放的,在内存中就相当于将每一行拆分后拼在一起,这也是为什么行可省略列不可省略。

第一行arr [ 0 ] [ j ],第二行 arr [ 1 ] [ j ]……

第一列arr [ i ] [ 0 ],第二行 arr [ i ] [ 1 ]……

二位数组也是一维数组的数组(有点小绕哈)

行数:sizeof ( arr ) / sizeof ( arr [ 0 ] )   总大小除以第一行大小即为行数

每行元素个数:sizeof ( arr [ 0 ] ) / sizeof ( arr [ 0 ] [ 0 ] )每一行大小除以其中一个元素大小即为每一行元素个数

3.数组越界

定义:数组下标小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

C语言不做下标越界检查,且编译器不一定报错,但并不代表程序是正确的,所以我们自己要做越界的检查。(不要偷懒哦)

4.数组作为函数参数

4.1冒泡排序

排序:冒泡排序,选择排序,插入排序,快速排序

这里我们只介绍一个简单的方法:冒泡排序

冒泡排序思想:两两相邻元素比较,一趟冒泡排序搞定一个数字,让这个数字来到最终应该出现的位置上,n个数字进行n-1趟。

// 对一组整数升序(从小到大)排列

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void 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[] = { 2,4,3,7,9,6,1,5,8 ,0};
	int sz = sizeof(arr) / sizeof(arr[0]);//这行代码不能放在sort函数里
	sort(arr,sz);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

 4.2数组名

由上图可知数组名是数组首元素的地址

两个例外:1> sizeof(数组名),这里的数组名是表示整个数组,计算的是整个数组的大小,单位是字节;2> &数组名,这里的数组名也表示整个数组,&数组名取出的是数组的地址

观察上述代码运行结果可知,前两组数据都加了4,而最后一组数据加了28(16进制),转换为十进制为40,说明&arr 指的是整个数组,加一跳过的是整个数组的字节(4*10)。

其实指针+1,到底跳过几个字节,是和指针类型有关的 

传参时,写成数组或指针都可以

数组传参本质上只传了首元素的地址

That‘s all~下回见啦,今天仍是爱敲代码的菜菜,有bug请指正哦~ 


网站公告

今日签到

点亮在社区的每一天
去签到