作者:几冬雪来
时间:2023年2月7日
内容:C语言函数数组讲解
目录
前言:
数组内容讲解:
1.什么是数组:
2.数组的构成:
3.数组的初始化:
4.数组的要点:
5.一维数组在内存中的存储:
6.二维数组的创建:
7.二维数组的初始化:
8.二维数组在内存的存储:
9.二维数组和一维数组的关系:
10.数组越界:
结尾:
在上一篇博客中我们正式结束了我们C语言的函数部分内容,并学习了斐波那契函数的原理和使用方法,这也让我们对C语言的了解更进一步,那么为了攀登更高的山峰,今天我们将学习C语言中的新内容,C语言数组。
数组我们已经运用过了许多次,在写三子棋的时候用到了,平常写题也多多少少用到了一些,但是我们那只是使用数组,我们有真正的了解过C语言的数组吗,那应该是没有的。所以接下来我们将对数组进行深入的了解。
按照惯例,要了解一个东西就要知道一个东西,那么什么是数组呢?数组(Array)是一种用来存储同一种类型的集合,并且数组中的每一个元素的地址是连续的。我们可以通过使用数组来为我们开辟一块空间,用于存放我们单个类型的多个元素。
了解完了什么是数组,接下来我们就讲解一下数组的构成。正所谓每个东西都有它的构成,就像我们的整形变量一样,它是又一个类型加上一个变量名组合而成的。那么我们的数组又是怎么样构成的呢?
如图所示,我们的数组就是由以上的3个部分组合而成的。
类型是由我们自己决定的,如果我要我开辟的这块空间存类型是字符类型,我们就只需要将变量名前面的类型改为“char”类型即可。
“[]”则是我们的一个常量表达式,括号里面输入的数字为开辟数组空间的大小,但是并不是括号内一定要数字才能初始化我们的数组,有的时候我们也可以不用输入,这个就先暂时不讲。
注:“[]”中不能放变量名,只能输入常量,c99编译器例外。
例:int arr[3];√ int arr[n];×
理解数组的构成后,要真正的使用数组,就应该和初始化整形一样对数组进行初始化,给数组内容一些合理的值。那么数组是怎么样初始化的?又有几种初始化的方法?
我们现在就对其进行一一分析并拓展。
int main()
{
int arr1[5] = { 1,2,3,4,5 };//完全初始化
int arr2[5] = { 1,2,3 };//不完全初始化,后面的元素默认为0
int arr3[] = { 1,2,3,4,5 };//不初始化元素的个数,编译器根据初始化内容判断个数
int arr4[] = { 1,2,3 };//3个元素
int arr5[10] = { 1,2,3 };//10个元素
char arr6[] = { 'a','b','c' };//3个元素
char arr7[3] = { 'a','b','c' };//3个元素
char arr8[10] = "abc";//10个元素
char arr9[] = "abc";//4个元素
return 0;
}
这里我们要注意arr6和arr9在打印的时候会出现的问题,看似两个数组都存放3个元素,但是打印出来的时候有所不同。
这里是为什么呢,因为在arr6中我们存放了3个元素,但是打印的时候要打印到‘\0’的时候,函数才会停止打印,因此在这个数组中打印完了原本的3个元素后,会继续打印下去随机值,直到到达‘\0’的时候结束。
在arr9中,我们不仅存放了3个元素,并且在3个元素的后面默认存放了‘\0’。因此在打印的时候我们就打印出来3个元素。
以上我们都是用‘%s’来打印出整个数组,但是如果我们要依次打印出数组中的每一个元素的时候,我们又应该这么做,要搞清楚什么?
1.数组是有下标的,数组的下标从0开始
2.[]为下标访问操作符
在了解完了这些之后,我们就来着手写一道题目。
题:打印数组的每一位元素。
这就是我们的代码,i从0开始,在i小于sz的时候i进行++,并且赋予数组里面,因为数组的下标是从0开始的,所以我们不能是小于等于。
在我们编写并打印的时候,我们的编译器就会为代码开辟一块可以存储它的空间。那么一维数组是如何在内存中存储的呢?我们将刚刚的代码稍微改进一下,然后再打印出来。
这里我们可以看出,在数组中,每一个元素的地址都是连续的,每两个元素之间都空有4个字节的大小。又因为我们的类型为整形类型,一个整形为4个字节,所以我们的存储和我们开辟数组的类型有关。
这样我们就可以得出一些结论。
1.一维数组在内存中是连续存放的。
2.随着数组下标的增长,地址是由低到高变化的。
那我们换个思考方向,数组中的每一个元素都有它的地址,那么我们能不能通过首元素的地址依次找到后面的所有元素?那当然是可以的,接下来我们就来试试看。
我们知道了数组首元素的地址后,将它的地址赋予给p,每次循环完,我们都把p的地址加上1。地址加一,又因为我们的类型是整形,所以跳过一个整形的地址,也就是4个字节,接下来找到我们下标为1的地址的值,并打印出来。
因为我们经常使用到一维数组,使用对一维数组会有所了解。但是二维数组可能就很少人有听说过了。那么二维数组又是应该怎么创建的呢?我们来看看。
我们可以看出来相比较一维数组,二维数组则是在一维数组中多了一个‘[]’。其余的并没有什么不同的地方。
跟一维数组一样,二维数组也要进行数组的初始化。那么二维数组是怎么样进行初始化的?
相对于一维数组,二维数组不仅仅是在创建的时候多了一个‘[]’,有的二维数组在初始化的时候也多了‘{}’。在二维数组进行初始化的时候,第一个括号表示行,第二个括号则表示列。
我们就以第一个二维数组为例,假设我要在数组中一次性放12个元素它是怎么样放的。
同样的二维数组也有不完全初始化,和一维数组一样也是将剩下的元素默认初始化为0。
但是如果我们不想依次存放,我想第一行只存储1,2。第二行存放3,4。第三行存放5,6我们又应该怎么写呢?
这里就牵扯出我们上面的第二个二维数组。
在我们第一行想存放的值再用应该‘{}’ 括起来,第二行和第三行也使用这个方法就能达成我们上图的效果。如果我们想一行存放3个的话我们只需要将'{}'中的再加入一个元素即可。
当我们要在二维数组中寻找某一个元素也是非常简单,只需要将这个元素的行和列输入即可。假设我们创建一个2行5列的数组,输入1~10的数字后要找到我们10这个元素,我们就只需要输入10这个元素的下标就可以找到。
注:二维数组的行可以省略,但是列不能省略。
那二维数组和一维数组在内存中的存储有什么区别吗,同样的我们将代码给写出来。
从我们的代码和结果中可以看出,和一维数组相对比,二维数组也是每一个元素中间因为整形类型有4个字节的大小。 在我们的画图中,我们的二维数组看似是多行多列的,但是实际操作起来我们才发现,二维数组其实是像一维数组一样在内存中连续存放的。因此我们得出结论。
二维数组和一维数组一样在内存中也是连续存放的。
同样的,我们也可以将二维数组中首元素的地址取出,赋值给‘p’,然后以打印一维数组的方法将二维数组的每一个元素打印出来。
从上面来看二维数组和一维数组可谓是十分相似,那么二维数组和一维数组之间有什么紧密连接的关系呢?
我们可以将每一个空格都看成是一个一维数组,有因为这样的一维数组一共有3个,它们被存放在二维数组中,所以我们得出结论。
二维数组是一维数组的数组。
讲到我们的下标访问操作符就不得不讲我们的数组越界了。
首先,数组的下标是有范围限制的。数组的下标是从0开始的,假设我们一共有n个元素,那么数组的下标大小就不能超过n-1。如果数组的下标小于0或者是大于n-1,这个时候我们就说数组越界了。
但是数组越界在C语言的编译器中并不会报错,所以我们在写数组的时候不要写出数组越界的代码。
一维数组和二维数组都可能发生数组越界的情况。
眨眼之间,我们又开启了C语言函数的新篇章。新篇章的开启也意味着我们对C语言的进一步理解,有点同学可能不久或者最近就要返校了,希望大家返校后依旧可以保存着学习的热情,我们可以要求共同学习,最后希望这篇博客能给各位提供帮助。