目录
一、一维数组
1.一维数组的创建
2.一维数组的初始化
3.一维数组的使用
4.一维数组的存储
二、二维数组
1.二维数组的创建
2.二维数组的初始化
3.二维数组的使用
4.二维数组的存储
三、数组越界
四、数组作为函数参数
冒泡排序
五、总结
一、一维数组
1.一维数组的创建
首先我们要了解数组是什么,数组是一组相同类型元素的集合,数组中会存放一组数。
数组的创建方式如下:
int arr[10] = { 1,2,3,4,5,6,7,8,9,0};
这里可以看见,我们创建的类型是int,创建的数组名是arr,它包含了10个元素,为0,1,2,3,4,5,6,7,8,9.
那么,[]内我们刚刚放的是常量10,它里面可以放变量吗?根据规定,数组创建,在C99标准之前,[]中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。
2.数组的初始化
根据第二点,我们知道数组的大小可以通过计算得到,我们创建一个数组:int arr[] = {1,2,3};
我们可以使用sizeof来进行计算,sizeof(arr)是整个数组的大小,sizeof(arr[0])是数组中一个元素的大小,我们用sizeof(arr)/sizeof(arr[0])就可以求出数组的大小啦,我们看一下代码:
通过以上两点,我们可以尝试写一个代码,利用数组在屏幕上打印0—9:
4.一维数组的存储
接下来我们探讨数组在内存中的存储。
首先我们定义一个数组 int arr[3] = {1,2,3}; 我们在来看看三个元素分别对应的地址:
我们把结果拿出来看:&arr[0]=0000000EAE2FF8B8
&arr[1]=0000000EAE2FF8BC
&arr[2]=0000000EAE2FF8C0
我们发现每个地址之间相差4个字节,随着数组下标的增长,元素的地址,也在有规律的递增。
二、二维数组
1.二维数组的创建
二维数组创建的方式和一维数组一样,不同的是它的下标引用操作符有两个,第一个代表行,第二个代表列。例:我们想创建一个三行四列的整型数组 int arr[3][4];
2.二维数组的初始化
二维数组初始化,每行内容用大括号括起来,大括号内每个元素用逗号隔开,每列之间也用逗号隔开,最外面有一个大括号将所有元素括起来。
I. int arr[3][4] = {1,2,3,4}; //初始化了第一行的内容,第二行和第三行默认都是0.
II. int arr[3][4] = {{1,2},{4,5}};//初始化了第一行的第一,第二列元素,分别为1和2。 // 初始化了第二行的第一,第二列元素,分别为4和5。其余都默认是0.
III. int arr[][4] = {{2,3},{4,5}};//二维数组如果有初始化,行可以省略,但是列不行
IIII. int arr[2][2] = {1,2,3,4}; //如果没有使用大括号分隔每行元素,则按顺序补充,补满第一行就自 //动换行补充。
3.二维数组的使用
二维数组的使用基本和一维数组一样,不管是行还是列,二维数组下标也都是从0开始的,如我们初始化一个三行两列的二维数组: int arr[3][4] = {{1,2},{3,4},{5,6}}; 我们想在屏幕上打印5,那么打印的行下标为2,列下标为0, 就是arr[2][0],我们可以看一下代码:
我们也可以通过二维数组在屏幕上打印0-5:
4.二维数组的存储
我们可以想一维数组一样,打印它每个元素地址进行查看:
这是其运行结果:
&arr[0][0]=00000040F892F898
&arr[0][1]=00000040F892F89C
&arr[0][2]=00000040F892F8A0
&arr[1][0]=00000040F892F8A4
&arr[1][1]=00000040F892F8A8
&arr[1][2]=00000040F892F8AC
我们发现每个地址之前还是相差4个字节,由此我们可以发现,二维数组在内存中也是连续存储的。
三、数组越界
我们可以利用一个代码进行讲解:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <= 10; i++)//当i=10的时候,就越界访问了
{
printf("%d\n", arr[i]);
}
return 0;
}
我们发现其实这个代码是错误的,在用for循环时候,其的条件判断部分是i<=10,这会导致程序访问了数组中下标从0—10的元素,有11个元素,但是数组arr中只有10个元素,这就会造成数组越界,但是程序是能跑起来的,我们来看运行结果:
我们可以发现运行结果是错误的,最后出现了一个错误的数字,但是程序并没有报错,可以正常运行,所以这种越界的错误就需要我们程序员自己进行检查。我们也要注意:二维数组的行和列也可能存在越界。
四、数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传给函数。数组传参,传递的是首元素地址
下面我们来写一个降序的冒泡排序的函数:
首先我们要知道什么是冒排序:通关两两相邻的元素进行比较和交换,从而实现数组中的数按一定顺序进行排序,而一趟冒泡排序可以让一个值来到最终应该出现的位置上。
所以我们要明确我们的目标
1.确定冒泡排序的趟数
2.一趟冒泡排序的实现
对于1,我们可以先求出数组包含的元素个数,随后从第一个数和第二个数开始进行比较和交换,最终交换完毕。
对于2,我们需要进行一定判断,代码如下:
if (arr[j] < arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
现在我们来写一下这个代码:
void bubble(int arr[10], int sz)
{
int i = 0;
for (i = 0; i < 10; i++)
{
int flag = 1;
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;
flag = 0;
}
}
if (flag == 1)
{
break;
}
}
}
int main()
{
int i = 0;
int arr[10] = { 4,1,5,6,8,3,7,9,2,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble(arr, sz);
for (i = 0; i < 10; i++)
{
printf("%d", arr[i]);
}
return 0;
}
这样子,我们就可以顺利的实现冒泡排序了,要注意:
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。