C语言程序设计笔记---011
- C语言数组
- 1、一维数组的创建和初识化
- 2、数组的初识化
- 3、一维数组的使用
- 3.1、一维数组在内存中的存储
- 4、二维数组的创建和初识化
- 4.1、二维数组的使用
- 4.1.1、打印二维数组的元素例程
- 4.2、二维数组在内存中的存储
- 4.3、数组越界
- 4.3.1、数组越界例程
- 4.4、数组作为函数的参数
- 4.4.1、数组名是什么?
- 5、结语
C语言数组
/知识点汇总/
1、一维数组的创建和初识化
概念:
数组就是一组相同类型元素的集合,或者说表示类型相同的数据
数组的创建方式:
type_t arr_name[const_n];
//type_t ---- 数组的元素类型
//arr_name ---- 数组名
//const_t --- 常量表达式,指定数组的大小
举例说明数组的创建:
#include <stdio.h>
int main()
{int arr[5];int arr2[2 + 3];char arr3[8];//C99之前数组只能是常量来指定大小//C99之后引用了变长数组的概念,数组的大小就可以使用变量来指定了//但是C99标准下,数组的大小可以使用变量指定,但是数组不能初识化//但是Vs2022/Vs2019 不支持C99的变长数组int n = 0;scanf("%d",&n);int arr4[n];return 0;
}
2、数组的初识化
概念:
数组的初识化是指,在创建数组的同时给数组的内容一些合理初始值(初识化)
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3 };//不完全初识化,剩余元素默认补0int arr2[4] = { 1,2,3,4 };//完全初始化char arr4[3] = { 'a',98,'c' };int arr3[] = {1,2,3};//省略数组大小, 由编译器自行判断数组内的元素char arr7[] = {'a','b','c'};//'/0'字符串结束标志char arr8[] = "abc";return 0;
}
3、一维数组的使用
[] —> 下标引用符
#include <stdio.h>
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n",arr[5]);//6//通过[]下标引用操作符,打印数组元素int i = 0;//for (i = 0; i < 10; i++)//{// printf("%d\n",arr[i]);//}//计算数组元素个数int sz = sizeof(arr) / sizeof(arr[0]);//更改元素for (i = 0; i < sz; i++){arr[i] = 10 - i;}for (i = 0; i < sz; i++){printf("%d\n", arr[i]);}return 0;
}
3.1、一维数组在内存中的存储
观察存储情况
#include <stdio.h>
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//通过[]下标引用操作符,打印数组元素int i = 0;//计算数组元素个数int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){printf("&arr[%d] = %p\n",i,&arr[i]);//&arr[0] = 0019F908//&arr[1] = 0019F90C//&arr[2] = 0019F910//&arr[3] = 0019F914//&arr[4] = 0019F918//&arr[5] = 0019F91C//&arr[6] = 0019F920//&arr[7] = 0019F924//&arr[8] = 0019F928//&arr[9] = 0019F92C//观察结果可知,相邻元素之间相差4,单位字节}return 0;
}
小结:
(1)、数组在内存中是连续存放的
(2)、随着下标的增长,地址是由低到高变化的
4、二维数组的创建和初识化
[ ][ ] – 几行几列
#include <stdio.h>
int main()
{int arr[3][5];//整型二维数组创建char arr2[4][10];//字符型二维数组创建int arr3[2][3] = {0};//char arr4[3][5] = {1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};char arr4[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };//大括号的作用约束,元素是否按照顺序放满之后再存放下一行int arr5[4][10] = { {1,2},{2,3,4},{5,5,5} };//注意:行可省略,列不可以省略//因为列确定一行所放的元素,行根据初识化几行就放几行int arr6[][3] = {1,2,3,4,5,6,7,8,9};//3行3列return 0;
}
小结:
(1)、对于二维数组,如果初识化了,对于行数是可以省略的,但列是不能省略的
(2)、大括号的作用约束,元素是否按照顺序放满之后再存放下一行
4.1、二维数组的使用
二维数组的访问依然是通过下标进行访问
4.1.1、打印二维数组的元素例程
#include <stdio.h>
int main()
{int arr[3][5] = { {1,2},{4,5},{6,7,8} };int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ",arr[i][j]); }printf("\n");}return 0;
}
#include <stdio.h>
int main()
{int arr[3][5] = { {1,2},{4,5},{6,7,8} };int i = 0;//数组元素1~15for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){arr[i][j] = i * 5 + j + 1;}}//打印1~15数组元素for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}
4.2、二维数组在内存中的存储
#include <stdio.h>
int main()
{int arr[3][5] = { {1,2},{4,5},{6,7,8} };int i = 0;//打印数组元素for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){printf("&arr[%d][%d] = %p\n",i,j, &arr[i][j]);//&arr[0][0] = 00AFFC00//&arr[0][1] = 00AFFC04//&arr[0][2] = 00AFFC08//&arr[0][3] = 00AFFC0C//&arr[0][4] = 00AFFC10//&arr[1][0] = 00AFFC14//&arr[1][1] = 00AFFC18//&arr[1][2] = 00AFFC1C//&arr[1][3] = 00AFFC20//&arr[1][4] = 00AFFC24//&arr[2][0] = 00AFFC28//&arr[2][1] = 00AFFC2C//&arr[2][2] = 00AFFC30//&arr[2][3] = 00AFFC34//&arr[2][4] = 00AFFC38//通过结果可知,相邻的元素间隔是4,单位字节//连续存放的,第一行放完接着第二行放//行数可以省略,列数不可以省略//随下标的增长,地中也是由低到高的存放的}printf("\n");}return 0;
}
小结:
(1)、通过结果可知,相邻的元素间隔是4,单位字节
(2)、连续存放的,第一行放完接着第二行放
(3)、二维数组可理解为一维数组的数组
(4)、行数可以省略,列数不可以省略
(5)、随下标的增长,地址也是由低到高的存放的
(6)、二维数组名:
如:arr[m][n] ---->数组名为arr[m]
4.3、数组越界
数组的下标规定是从0开始的,如果有n个元素,那么最后一个元素的下标就是n-1,
所以,当数组的下标小于0或大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
另外,C语言本身并不会进行越界检查,部分编译器也不一定会进行报错,容易导致程序出现难以发现的bug
4.3.1、数组越界例程
#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6};//下标0~9int i = 0;for (i = 0; i <= 10; i++)//下标=0时,数组越界{printf("%d ",arr[i]);//数组越界}return 0;
}
4.4、数组作为函数的参数
数组可以作为函数的参数
经典的冒泡排序
核心思想:两两相邻的元素比较
冒泡排序的思路:
第一趟:
10 9 8 7 6 5 4 3 2 1
9 10 8 7 6 5 4 3 2 1
9 8 10 7 6 5 4 3 2 1
......
9 8 7 6 5 4 3 2 1 10//此时完成一趟冒泡排序,将第一个元素排到了最后
第二趟:
8 9 7 6 5 4 3 2 1 10
8 7 9 6 5 4 3 2 1 10
.....
8 7 6 5 4 3 2 1 9 10//此时完成二趟冒泡排序,将第二个元素排到了最后
......
依次类推:
直至完成升序排序
数组作为函数的参数例程 — 冒泡排序
#include <stdio.h>
int main()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//降序//将arr数组进行排序,排序为升序//冒泡排序int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//趟数for (i = 0; i < sz-1; i++){int j = 0;for (j = 0; j < sz - 1-i; j++)// sz - 1-i元素比较的对数{if (arr[j] > arr[j + 1])//交换{int temp = 0;temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}for (i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
数组作为函数的参数例程 — 函数写法 – 待优化
#include <stdio.h>void 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++)// sz - 1-i元素比较的对数{if (arr[j] > arr[j + 1])//交换{int temp = 0;temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}int main()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//降序//将arr数组进行排序,排序为升序//冒泡排序int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
小结:
发现数组传参过去,代码执行结果与预想不同
探讨数组传参
4.4.1、数组名是什么?
数组名就是地址,通常来说数组名就是数组首元素的地址
但是有两个例外:
(1)、sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
(2)、& — 取地址操作符 —> &数组名,表示整个数组,取出的是整个数组的地址
除此之外,所遇到的数组名都是数组首元素地址
数组名例程
#include <stdio.h>
int main()
{int arr[10] = { 0 };printf("%p\n",arr);printf("%p\n", &arr[0]);printf("%d\n", sizeof(arr));//对数组名进行加1的情况printf("%p\n", arr);printf("%p\n",arr+1);//+4printf("%p\n", &arr[0]);printf("%p\n",&arr[0]+1);//+4printf("%p\n",&arr);printf("%p\n",&arr+1);//+28(十六进制) --> +40(十进制),加的整个数组大小return 0;
}
小结:
(1)、sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
(2)、& — 取地址操作符 —> &数组名,表示整个数组,取出的是整个数组的地址
(3)、数组传参的本质就是传首元素的地址
探讨了数组名作为参数的知识,再回到冒泡排序
数组作为函数的参数例程 — 冒泡排序函数写法 — 优化
#include <stdio.h>
//首元素地址,本质就是指针接收参数int arr[] ----> int* arr即可等价
void 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++)// sz - 1-i元素比较的对数{if (arr[j] > arr[j + 1])//交换{int temp = 0;temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}
int main()
{int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//降序//将arr数组进行排序,排序为升序//冒泡排序int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);sort(arr,sz);//学习了什么是数组名,可知这里的arr,不是特殊情况,就是数组的首元素地址for (i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
5、结语
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)