c语言-数组篇

【前言】本系列(初阶)适用于初学者课前预习或者课后复习资料,包含了大部分基础知识点梳理与代码例方便看官理解,有问题请指出。本人邮箱地址:p772307283@outlook.com

 可爱捏

1.数组的创建与初始化

1.1数组创建

数组的定义非常简单,就是一组相同类型的元素的集合。 

其创建的方式为

type  arrname[const n];
//type是数组的元素类型
//arrname是数组名
//const n是常量表达式,用以指定数组大小

需要知道的是,在C99之前,[]中必须给出常量,但C99支持了变长数组,数组大小可由变量指定,但变长数组不可以初始化

 1.2数组初始化

初始化的意思就是在创建数组时对数组内容给出合理的初始值。 

int arr1[10] = { 1,2,3 };

这被称为不完全初始化。后面的元素被默认为了0(可通过监视窗口查看)。

int arr2[] = { 1,2,3 };

数组中未给定const n,这是合法的。系统根据后面的元素个数来确定const n

int arr3[3] = { 1,2,3 };

所有要素都具有的数组。

char数组也是同理,但是char有几个需要注意的地方。

char数组的内存是如何分配的呢?

#include<stdio.h>
int main()
{
	char arr1[] = "abc";
	char arr2[] = { 'a','b','c' };
	printf("%s\n", arr1);
	printf("%s", arr2);
}

编译运行,arr2的打印不符预期,在abc后面跟上了一大串的“烫烫烫”和其他文字。

这是因为arr2区别于arr1的地方在于,arr1确保了在最后一个字符后跟上了一个'\0',作为字符串的结束方式。而arr2的'\0'具有随机性,你不知道在距离最后一个字符的什么地方才能找到他。

并且了解过栈帧的看官知道,在main的栈帧空间里,会先预填入很多的0xcccch,而0xcccch就是汉字烫的编码。

1.3一维数组使用

数组使用下标引用操作符[]

在这里只需要了解其输入和输出。

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	//输入
	for (int i = 0; i < sizeof(arr) / sizeof(arr[1]); i++)
	{
		arr[i] = i;
	}
	//输出
	for (int i = 0; i < sizeof(arr) / sizeof(arr[1]); i++)
	{
		printf("%d ", arr[i]);
	}

}

其中需要注意的是如何求取整型数组的长度。

通常我们使用sizeof的方式来解决。以整段数组字节大小除以一个小段的字节大小,就能得到数组有多少个小段,也就能得到数组的长度了。

还有一点:数组通过下标进行访问,且开始的下标为0

那么一维数组是如何进行存储的呢?结论是:数组在内存中是连续存放的。

以代码示例来证明

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

	}
	return 0;
}

得到的运行结果 

&arr[0]=00000099B32FFCA8
&arr[1]=00000099B32FFCAC
&arr[2]=00000099B32FFCB0
&arr[3]=00000099B32FFCB4
&arr[4]=00000099B32FFCB8

显而易见这是十六进制,从8到c,是差4个字节,以此类推,每个小段都占有4个字节,也正好对应了int,其地址也是连续的。

2.二维数组

2.1二维数组的创建与初始化

int arr[3][3] = { 1,2,3 };

这就是一个未完全初始化的二维数组。第一个3代表着有3排,第二个3代表着有3列,所以一共就是9个元素。

对于其初始化需要注意的有一点:行可以省但是列不可以省

很显然,如果只有行,不知道有多少列,你该如何去存放你的元素?

而只有列的话仍然可以对元素进行正常的存放。

2.2二维数组的使用

二维数组的使用同一维数组并无太大差异。

例如arr[3][3]

其排列为

arr[0][0]  arr[0][1]  arr[0][2]

arr[1][0]  arr[1][1]  arr[1][2]

arr[2][0]  arr[2][1]  arr[2][2] 

#include<stdio.h>
int main()
{
	int arr[3][3] = { 0 };
	//输入
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			arr[i][j] = i + j;
		}
	}//输出
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("arr[%d][%d]=%d\n", i, j, arr[i][j]);
		}
	}
		return 0;
}

 得到结果:

arr[0][0]=0
arr[0][1]=1
arr[0][2]=2
arr[1][0]=1
arr[1][1]=2
arr[1][2]=3
arr[2][0]=2
arr[2][1]=3
arr[2][2]=4

 同样的,二维数组的地址也是连续存放的。可以自行验证。

可以将第一排看作第一个一维数组,第二排看作第二个一维数组,第三排看作第三个一维数组,这三个一维数组存放是连续的。

小tip:数据越界

数组的下标具有范围的限制。例如一个元素只有n个元素,但如果下标为n,则是数组越界。

因为下标总是由0开始的

数组的越界可能编译器无法察觉,所以还请大家在编写代码时小心甄别。

二维数组也存在类似的情况捏。

3.以冒泡排序讲解数组函数传参

冒泡排序是几种经典排序算法中最简单的一种,其思想在于 通过多次循环进行遍历,例如一个长度为10的数组,第一次遍历9次,第二次则遍历8次,直到遍历完整个数组,在遍历的同时对其进行排序。

对这个数组进行升序的操作

第一趟让9与剩下的元素进行比较,最坏的情况下需要比较9次。

9 8 7 6 5 4 3 2 1 0 

8 9 7 6 5 4 3 2 1 0

8 7 9 6 5 4 3 2 1 0

。。。。。。

8 7 6 5 4 3 2 1 0 9

这样就让9来到了最终的位置。以此类推接着用同样的方法操作8 7等数字,但10个数字只需要冒泡排序9趟,当9个元素都来到了合适的位置上时,剩下的那一个就已经自动的排在合适的位置了。

那么代码如下:

void bubblesort(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[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 tmp;
			tmp = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = tmp;
            }
		}
	}
}
int main()
{
	int arr[] = { 3,6,8,2,1,9,5,4,7,0 };
	bubblesort(arr);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

但是你在运行后发现了问题,其数组并未按照预定的想法进行排序。那是哪里出现了问题呢?

对程序进行监视就可以知道,sz的值一直都是1,那么问题就看出来了,sz等于1,后面的循环直接就卡住了。

那么是什么导致了sz的值是1呢?

答案是传参传进来的arr。数组作为参数进行传递时传进函数会退化成指针。也就是说其实sizeof(arr)计算的并非整个数组的大小,而是arr这个指针的大小,arr时int型的指针,大小为4字节,arr【1】的大小也是4字节,就导致了sz=1了。

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

 更改完成。

sizeof(数组名),计算的是整个数组的大小。sizeof内部的数组名就代表整个数组

&数组名,取出了数组的地址,此时的数组名也代表整个数组

其他情况下,数组名都表示首元素的地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值