1. 二维数组的创建:
int arr[][];
long arr[][];
double arr[][];
在这,格式就是数据类型 数组名称 [ 数组的行] [ 数组的列 ];
int arr [ 3 ][ 4 ];此时就写了一个数组,这个二维数组的长度就是3行4列.
2. 二维数组的初始化:
int arr [3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
此时就是对这个二维数组进行了初始化,对这个二维数组添加了数据元素.那么此时这个二维数组初始化以后的状态就是
1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 |
int arr [3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int arr [][4] = {1,2,3,4,5,6,7,8,9,10,11,12}
对二维数组这样的遍历也是可以得到上面的情况的.
注意在二维数组的初始化时,二维数组的列是不可以省略的.
下面我们来输出一下这个二维数组:
#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++){//因为我们数组的行和列的角标是从0开始的;这里我们从行开始
int j = 0;
for(j=0;j<4;j++){//这里我们从列入手
printf("%d", arr[i][j]);//打印这个数组
}
printf("\n");
}
}
上面代码运行以后就是我们二维数组的打印.
那么二维数组的数据元素并不是固定的嘛,那我们就来给这个二维数组添加可以自己增加数据元素的条件:
#include<stdio.h>
int main(){
int arr [3][4] ;;
int i = 0;
for(i=0;i<3;i++){//因为我们数组的行和列的角标是从0开始的;这里我们从行开始
int j = 0;
for(j=0;j<4;j++){//这里我们从列入手
scanf("%d", &arr[i][j]);
}
}
for(i=0;i<3;i++){//因为我们数组的行和列的角标是从0开始的;这里我们从行开始
int j = 0;
for(j=0;j<4;j++){//这里我们从列入手
printf("%d", arr[i][j]);//打印这个数组
}
printf("\n");
}
return 0;
}
那么二维数组在创建以后,我所给他的数据元素的个数并没有到达我所定义的数组的数据元素的个数时,比如说一下情况:
int arr[3][4] = {{1,2},{2,3},{3,4}}
此时我可以很明显的发现我定义的二维数组的是一个三行四列的,但是我在初始话的时候,很明显给数组的行上的数据元素不够,那么这个数组害正确嘛?
那么在C语言中,如果说你所定义的数组的长度在你初始化的时候并没有给够它足够的数据元素的时候,那么此时计算机就会自己在你的数组后面给你补齐元素数据(用0补齐).
#include<stdio.h>
int main(){
int arr [3][4] = {1,2,3,4,5,6,7};
int i = 0;
for(i = 0 ;i < 3; i ++){
int j = 0;
for(j = 0; j < 4;j++){
printf("%d",arr[i][j]);
}
printf("\n");
}
return 0;
}
输出的结果就是:
那么我们定义了一个数组,我们怎么来调用数组中的元素呢?
其实我们在调用数组中的元素的时候是通过数组元素的角标来访问数组元素的.
数组的行/列 | 0 | 1 | 2 | 3 |
0 | 1 | 2 | 3 | 4 |
1 | 5 | 6 | 7 | 8 |
2 | 9 | 10 | 11 | 12 |
上面我们初始化了一个数组:如果我们要访问数组中的某一个数据元素时,我们可以通过元素的下标了查询数据元素,比如说:我们要查询的是第2行第3列的元素:也就是我们的7,那么我们此时可以访问
arr[1][2]
那么为什么我在访问的时候,输入的是arr[1][2]不是arr[2][3]呢?那么在数组中,数组元素的下角标是从0开始的,行与列都是从0开始.
数组越界:数组角标是从0开始,最后一个元素是n-1,访问的数组的元素的角标的数字大于数组角标的最大值或者小于最小值,就出现了角标的越界. 角标越界的时候有时编译器不会报错.(C语言不做数组角标越界的检查,需要本人自己检查)
那么我们在访问二维数组的时候出现了这样的数组角标越界呢
arr [2][3] = {1,2,3,4,5,6}//我定义一个两行三列的数组,那么我此时在访问的时候不小心写错了
printf("%d",arr[0][3]);//此时我访问的数据元素是数组的第一行第四列的元素
那么此时我所访问的数据元素很明显出现了越界的情况,那么此时还会访问到元素嘛?在这就需要给大家说明一下二维数组在内存储空间中的位置.
在内存储空间中,二维数组是连续存储的,当我们访问的位置超出了第一行的角标的时候,此时就会直接越界到第二行去查找第一行后面的元素,也就是说,我们刚刚查找的数据元素是可以打印出来的,第一行第四列的元素并没有,但是会访问到第二行的第一列的元素,所以我们上面的代码是可以访问到数据元素的,它的输出值就是4,那么此时出现了数组的角标越界,那么程序仍然可以执行并且不会报错,所以以后在写代码的时候需要自己多注意这些细节,避免出现数组角标越界的情况.
数组作为函数参数:数组在传参的时候只需要加上数组名 ,在这作为传参的时候,就不得不拿出我们的一个排序算法来给大家举例子了.
注意: 在函数内部传数组时,其实传过去的是一个指针,如果说需要传过去数组的大小的时候,我们可以在函数外面传数组的长度,这样就可以防止传进去的指针不等于数组的长度从而出现排序中的错误.
在函数外部传数组的长度值:
#include<stdio.h>
void paixu(int arr[],int size) {
int i = 0;
for (i = 0; i < size; i++) {
int j = 0;
for (j = 0; j < size- i-1 ; j++) {
if (arr[j] < arr[j+1]) {
int tep = arr[j+1];
arr[j+1] = arr[j];
arr[j] = tep;
}
}
}
}
int main() {
int arr[] = {1,2,3,4,5,6};//我们定义一个数组
int size = sizeof(arr) / sizeof(arr[0]);
paixu(arr,size);
int i = 0;
for (i = 0; i < size; i++) {
printf("%d", arr[i]);
}
return 0;
}
此时我们发现这样的一个冒泡排序就可以正常的排序
那我们在函数内部传数组的长度:
#include<stdio.h>
void paixu(int arr[]) {
int i = 0;
int size = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < size; i++) {
int j = 0;
for (j = 0; j < size - i - 1; j++) {
if (arr[j] < arr[j + 1]) {
int tep = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = tep;
}
}
}
}
int main() {
int arr[] = { 1,2,3,4,5,6 };//我们定义一个数组
int size = sizeof(arr) / sizeof(arr[0]);
paixu(arr);
int i = 0;
for (i = 0; i < size; i++) {
printf("%d", arr[i]);
}
return 0;
}
此时我们们发现,在函数的里面传送数组的长度的时候,并没有排序
这在我们给大家输出一下此时的size的值
void paixu(int arr[]) {
int i = 0;
int size = sizeof(arr) / sizeof(arr[0]);
此时输出的size的值是1,说明我们在函数的内部传进去以后,我们只循环了一次,说明我们的循环就没有执行.
在函数内部传数组时,其实传过去的是一个指针,如果说需要传过去数组的大小的时候,我们可以在函数外面传数组的长度,这样就可以防止传进去的指针不等于数组的长度从而出现排序中的错误. 什么意思呢?就是我们在上面的排序的函数中传过去的数组,它并不是真正的数组,而是指针的变量.,在这里要给大家说明一下,数组的名字它本质上是这个数组首元素的地址.下面给大家来演示一下:
int main() {
int arr[] = {1,2,3,4,5,6};//我们定义一个数组
printf("%d", arr);
return 0;
}
此时我们看,我输出的数组的名,它并没有输出整个数组的值,而是输出了一串数字,那么这个数字就是这个数组首元素在内存储空间的一个位置.
数组名是什么?:数组名能表示首元素的地址,但是有两个例外.
1.sizeof(数组名):计算整个数组的大小 单位是字节
2.&数组名,数组名表示的是整个数组,表示的是整个数组的地址
整个数组的地址+1表示的是地址是数组的最后的一个元素的后一位的地址.
int n = sizeof(arr);//打印出n是?
#include<stdio.h>
int main() {
int arr[] = { 1,2,3,4,5,6 };//我们定义一个数组
int n = sizeof(arr);
printf("%d", n);
return 0;
}
此时输出的n的值是24,它输出的整个数组的一个长度,它里面有6个元素,每个元素占用4个比特位,
二维数组名的理解:二维数组的数组名也表示数组首元素的地址,表示的是二维数组的第一行的元素的地址.(将二维数组看成一维数组)
int main() {
int arr[3][2] = { 1,2,3,4,5,6 };//我们定义一个数组
printf("%p", arr);
printf("\n");
printf("%p", arr[0]);
return 0;
}
发现数组名所表示的和数组首元素的地址是一样的.所以说二维数组的数组名也表示数组首元素的地址.
arr 和arr+1相差的地址是一行的元素的距离.
int main() {
int arr[3][2] = { 1,2,3,4,5,6 };//我们定义一个数组
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("----------------\n");
printf("%p\n", arr[0]);
printf("%p\n", arr[0]+1);
return 0;
}
我们看到给数组名+1的时候,输出的值相差了8,给数组首元素的地址+1的时候发现增加了4,那么在二维数组中,如果说是给二维数组名的地址+1的时候,此时地址相差了一行数据的位数,上述代码中也就是两个数据元素8个比特位.(&arr 取得是整个二维数组的地址.)
数组的长度:sizeof(arr)/sizeof(arr[0])//表示的是数组的元素的个数,在这为什么要除以呢,因为sizeof(数组名)表示的是整个数组中的所有数据元素所占的内存空间,它除以其中的一个数据元素的存储空间就是整个数组的长度,在这大家要注意,不要混淆.下面代码给大家解释一下;
#include<stdio.h>
int main() {
int arr[]= { 1,2,3,4,5,6 };//我们定义一个数组
int i = sizeof(arr);
printf("%d\n", i);
int j = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", j);
return 0;
}
本次的分享就到这结束了!期待我们下期再见.