【逐步剖C】第三章-数组

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、一维数组

1. 一维数组的定义与使用

  • 1数组的简单概念一组具有相同类型的元素的集合

  • 2数组的创建
    格式类型名+数组名+[数组大小]
    需要注意的是对多数情况而言在指定的数组大小时需要用常量表达式。
    PS:若编译器支持C99则可使用变量来指定数组的大小即变长数组但变长数组有一些限制变长数组必须是自动存储类的意味着它们必须在函数内部或作为函数参数声明而且声明时不可以进行初始化。
    数组的大小可以省略但若想省略则必须在创建时就对其进行初始化。

  • 3数组的初始化
    和变量的初始化类似在创建它的时候赋予它一些合理的值
    一般的初始化形式数组名[数组大小]={…}
    数组的下标是从0开始的故需根据实际需求正确指定数组的大小
    若数组的大小省略则数组会根据初始化的内容来确定数组的大小
    如int arr[]={1,2,3};
    数组arr的大小就为3个整型变量的大小
    若数组的初始化部分即{ }中的元素达不到数组的大小时相应没有指定初始化的地方自动初始化为零称为数组的不完全初始化
    int arr[3] = {1};
    此时数组中对应的元素为 arr[0] = 1; arr[1] = 0; arr[2] = 0

故常通过如下面这段代码来实现对数组每个元素赋0的初始化

int arr[10] = {0};

对于作为全局变量的数组 其元素默认初始化为0

  • 4一维数组的使用通过下标引用操作符[ ]来实现对每个元素的访问
arr[2] = 2;
//将数组的第三个元素赋值为2
  • 5 可通过sizeof来计算数组的长度
int len = sizeof(arr)/sizeof(arr[0]);
  • 6易踩坑点用数组存储字符串的初始化

时刻要在脑海中的一个知识点字符串的最后一个字符是‘\0’这也是函数对字符串进行操作的标志如strlen strcmp等。故在用数组进行字符串的存储时一定要考虑到 \0 而正确指定数组的大小

如下代码

char arr[3] = { "abc"};

将其打印出来的结果是
​​​​在这里插入图片描述
解释此时数组的情况是arr[0] = ‘a’; arr[1] = ‘b’; arr[2] = ‘c’; 而‘\0’ 并没有被随着字符串存储到数组当中故在对其进行打印操作时找不到结束的标志 在打印完abc后又打印了乱码

结论对字符串来说其长度就为组成它的字符个数如上字符串“abc”的长度就是3而对数组来说还要另将字符串的结束标志 \0考虑进去。通过如下代码加深印象

int main()
{
	char arr1[3] = { "abc"};
	char arr2[3] = { 'a','b','c' };
	char arr3[4] = { 'a','b','c','\0' };
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	printf("%s\n", arr3);
	return 0;
}

打印结果
在这里插入图片描述

2. 一维数组在内存中的存储

先说结论数组在内存中是连续存放的且是从低地址到高地址即随着下标的增长其每个元素的地址也在有规律地递增。
如下代码展示

#include<stdio.h>
int main()
{
	int arr[5] = { 0 };
	int len = sizeof(arr) / sizeof(arr[0]);
//上面说的计算数组长度的方法
	int i = 0;
	for (i = 0; i < len; i++)
		printf("%p\n", &arr[i]);
	return 0;
}

运行结果
在这里插入图片描述

二、二维数组

1. 二维数组的创建和使用

  • 1格式
int arr [rows] [cols];

同一维数组 [ ] 中为常量表达式

  • 2初始化
int arr[2][2] = {1,2};
//数组的第一行的一二列的初始化
int arr[2][2] = {{1},{2}};
//数组的第一列的一二行的初始化
int arr[][2] = {1,2};
//数组的省略初始化但要注意行可以省略但列不能省略
  • 3使用同一维数组使用 [ ] 操作符进行访问。

2. 二维数组在内存中的存储

也和一维数组一样按地址由高到低连续存放
PS其实所谓行和列只是我们的一种理解其实二维数组的存放和一维数组一样是一整行的如下图

在这里插入图片描述
所以这里可以有一种理解方法把对应行如arr[0]看作是对应一维数组的数组名而再通过操作符 [ ] 中的数字来访问这个一维数组的每一个元素。即把二维数组当一维数组来使用。如arr[0][1]就可以理解为访问的是一维数组arr[0]的第二个元素
这里我们同样可以通过sizeof来对二维数组进行一些运算

//计算二维数组的行数
sizeof(arr) / sizeof(arr[0])

//计算二维数组每行元素个数
sizeof(arr[0]) / sizeof(arr[0][0])

三、补充知识

1.数组越界问题

所谓越界就是指访问的下标超过了数组的长度。需要注意的是C语言本身不做数组下标的越界检查编译器也不一定报错编译器不报错并不代表程序就本身是正确的。所以我们在写代码的时候一定要细心写完后最好做一遍越界的检查。

2.数组作为函数参数

先说知识点数组传参本质上传的是数组首元素的地址。这里就不得不谈到数组名的问题。
数组名其实就代表着该数组首元素的地址如下代码

int arr[5] = { 1,2,3 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d", *arr);

运行结果
在这里插入图片描述
当然也有两个例外情况

1用sizeof计算数组大小时中的数组名代表的时整个数组。

2&数组名其中的数组名也表示整个数组这个操作指的是取出整个数组的地址到指针总结时会更详细说明

3. 对数组类型的理解

int num = 10;

对于变量num而言 int 就是它的类型即去掉变量名
可以得到 sizeof(int) == sizeof(num)
对于数组而言其实是同样的道理

int arr[10];

对于上面这个数组arr而言呢int[10] 就是它的类型即去掉数组名
同理也有sizeof(int[10]) == sizeof(arr)

4. 数组作为函数参数的重要实例冒泡排序

补充冒泡排序的主要思想是相邻两数进行对比若不符合想要实现的序列升序或降序则两数进行交换
先来个错误的函数例子好涨记性

void bubble_sort(int arr[])
{
 int len = sizeof(arr)/sizeof(arr[0]);
//这里想求数组长度但调试发现结果不符合预期
    int i = 0;
 for(i=0; i<len-1; i++)
   {
        int j = 0;
        for(j=0; j<len-i-1; j++)
       {
            if(arr[j] > arr[j+1])
           {
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
           }
       }
   }
}

结果为1的原因上面说过用sizeof计算数组长度时中的数组名表示整个数组或着说应当为整个数组的地址而数组传参本质上传的是数组首元素的地址而地址的大小在32位机上位4个字节在64位机上为8个字节又因为该数组为整型数组其元素的类型大小为4个字节故最终的len的值只可能是2或1。

解决办法数组长度在外面算好后再传进去

改正并通过flag优化后的完成冒泡排序程序如下

void bubble_sort(int arr[], int n)
{
	int i, j;
	int tmp = 0;
	for (i = 0; i < n - 1; i++)		//趟数即有多少个数需要被处理
	{
		int flag = 1;		
		for (j = 0; j < n - 1 - i; j++)		//对换次数即一趟需对换多少次
		{
			if (arr[j] > arr[j + 1])		//本质上是想让不满足既定有序条件的两个数对换
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;				//当i=1时5和4就已发生对换整个数组已经有序									
			}
		}
		if (flag == 1)
			break;
	}
}

对flag优化的解释利用flag可以减少趟数优化代码用来解决可能提前排序完成的情况即已经有序了。因为n-1趟的规律是在完全倒序情况下总结的即数组为987…但实际上数组可能只需一趟就完成了排序
如12354。
如果没有flag的话代码依然会按照n-1趟来判断一些过程就重复了。
flag可以理解为是一个检测有序的标志
结合代码理解如上例{1,2,3,5,4}第一趟4和5发生对换对换后数组已经有序此时进行下一趟排序时内循环中的交换将一次都不进行也就是flag的值不会被置为0内循环结束时flag的值仍为1这就代表着数组已经有序就可以跳出循环了。

以上就是我对数组这一部分知识的总结啦。

看完觉得有觉得帮助的话不妨点赞收藏鼓励一下有疑问或有误地方的地方还恳请过路的朋友们留个评论多多指点谢谢朋友们🌹🌹🌹

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6