大家好这里是笨鸟先飞————博客持续更新中,这次为大家带来数组的进阶认识
目录
一维数组的创建和初始化
数组的创建
数组是一组相同类型元素的集合。
数组的创建方式
typt_t arr_name [const_n]
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来制定数组的大小
数组代码实例
//代码1
int arr1[10];
//代码2
int count ={10};
int arr2[count];//c99标准后支持这样创建
//代码3
char arr3[10];
double arr3[10];
请注意在代码2中,在c99标准之前 [ ] 中给一个常量才行,在c99标准之后支持变长数组。
数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
看代码:
不完全初始化,给10个元素只放4个,其余6个元素初始化为0
int arr1[10] = {1,2,3,4};
如果数组没给定长度,根据初始化的内容给长度
int arr2[] ={1,2,3,4};
如果给定数组的大小,和后面的元素的大小相等,就叫做完全初始化
int arr3[5] ={1,2,3,4,5};
char arr4[4] ={'a',95,'c'};
char arr5[5] ={'a','b','c'};
char arr6[7] ="abc";
字符串后面自带一个\0,
char arr7[7] ={'a','b','c'};
字符不带\0,所以他和上面还是有区别的
注意数组arr[6],arr[7]还是有区别的,虽然他们数组里放的都是abc0000。因为上面有一个0是字符串的结束标志,下面所有的0全是初始化形成的。
下面给大家看看调试的结果
一维数组的使用
数组在内存中是有编号的,并且他的编号是从0开始,这里的编号就是他的下标。
对于数组的使用我们之前介绍了一个操作符: [] ,下标引用操作符。它其实就数组访问的操作符。
int arr[]={1,2,3,4,5,6,7,8,9,10};
// [ ] 下标引用操作符
print{"%d",arr[4]}; //这里其实找的就是5的值,因为下标是从0开始的
int main()
{
数组不完全初始化
int arr[10]={0};
计算数组的元素个数
int sz = sizeof(arr)/sizeof(arr[0]);
对数组元素进行赋值,数组通过下标进行访问,下标是从0开始
int i = 0;
for(i=0;i<10;i++)
{
arr[i] = i;
}
//输出数组内容
for(i = 0;i<10,i++)
{
printf("%d",arr[i]);
}
return 0;
}
总结:
int [10] = {0,1,2,3,4,5,6,7,8,9};
初始化内容和数组给的大小相等,是完全初始化
int [ ] ={0,1,2,4,5,6,7,8,9};
数组大小会跟根据初始化内容给定。
int [10] ={0,1,2,3,4}
初始化内容小于于数组大小时会用0补齐
1.数组是使用下标来访问的,下标是从0开始的
2.数组大小可以通过计算得到。
int sz = sizeof(arr)/sizeof(arr[0])
一维数组的存储
接下里我们讨论一下一维数组在内存中的存储
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 0 };
int sz =sizeof(arr)/sizeof(arr[0]);
for(i=0;i<sz;i++)
{
printf("arr[%d]=%p\n",i,&arr[i]);
}
return 0;
}
由输出结果发现,随着数组下标的增长,元素的地址也在由规律的递增。
由此可以得出数组在元素中是连续存放的,并且地址从低到高。
二维数组的创建和初始化
二维数组的创建
//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
二维数组的初始化
int main()
{
//完全初始化
int arr[3][4] = { 1,2,3,4,5,8,9,7,4,4,6,5 };
int arr1[3][4] = { {1,2},{2,3},{4,5} };
//二维数组初始化时可以省略行,不能省略列
int arr2[][3] = { {2,1},{5,6},{7,8} };
return 0;
}
为了方便大家理解,还是画图说明二维数组的存储。
这里只是方便理解这样画,二维数组实际存储不是这样的。
二维数组的使用
二维数组的使用也是通过下标的方式,两个for循环嵌套就能搞定,一层循环输出行,一层循环输出列。
int main()
{
int arr[3][4] = { 1,2,3,4,5,8,9,7,4,4,6,5 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
通过这个两个for循环就能很好的输出出来。
二维数组的存储
注:
二维数组这里要注重理解,二维数组可以理解为一维数组的数组,每一行理解一维数组一个元素。
在访问二维数组时,可以看成一维数组的数组名+下标。
int main()
{
int arr[3][4] = { 1,2,3,4,5,8,9,7,4,4,6,5 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("&arr[%d][%d]=%p\n",i,j, arr[i][j]);
}
}
return 0;
}
这里我们看看二维数组 打印二维数组的地址,通过分析我们发现他们的地址相差都是4个字节,换行的差值也是4个字节。由此我们得出一个结论二维数组在内存中也是连续存储的。
所以实际二维数组在内存中是这样存储的。
数组越界
数组的下标是有范围限制的。
数组的下标是从0开始的,如果数组有N个元素,最后一个元素的下标就是N-1.
所以说如果数组的下标是小于0,或者大于N-1的时候就是数组越界访问了。
在下标访问越界时,编译器是不报错的,可以运行出来,所以程序员在写代码时需要仔细检查数组是否越界。
可以看到当我们数组越界访问时,这里的值是-858993460,这里其实的值-858993460其实是一个随机值。
数组作为函数参数
冒泡排序
冒泡排序的核心思想是相邻的两个元素进行比较,按照要求来交换他们的值。
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz-1; i++)
{
//一趟冒泡排序
int j = 0;
for (j = 0; j<sz-1-i; j++)
{
int tmp = 0;
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//计算元素个数,
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);
int i = 0;
//输出排序后的元素
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
这里就是冒泡排序的应用的代码,大家可以参考一下。
数组名是什么?
数组名确实表示首元素的地址
但是有两个例外
1.sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个函数名,数组名表示整个数组
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
大家可以存在疑惑输出arr的地址,和输出整个数组&arr打印的结果都一样,但他们只是表面一样,实际上是有区别的,分别给他们的地址+1后我们观察发现,arr的地址加了4个字节因为她只是取了首元素的地址,而&arr是整个元素的地址+1后,我们看到她的地址多了40个字节。因为这个数组里有10个元素,每个元素的大小是4个字节,给他+1相当于给整个数组的地址+1所以是40个字节
结语
码字不易,如果所写的内容对你有所帮助的话,一键三连哦!!!谢谢各位友友了!!!