目录
一.数组的创建和初始化
数组的创建
数组初始化
一维数组的使用
一维数组在内存中的存储
二.二维数组的创建和初始化
二维数组的创建
二维数组的初始化
二维数组的使用
二维数组在内存中的存储
三.数组越界
四.数组作为函数参数
数组名是什么
数组实例
一.数组的创建和初始化 数组的创建
数组是一组相同类型元素的集合,
数组的创建方式:
type_t arr_name [ const_n ]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式,用来指定数组的大小
数组创建的实例:
注: 数组创建,在 C99 标准之前, [] 中要给一个 常量 才可以,不能使用变量。在 C99 标准支持了变长数组的概念。即代码2 数组初始化 数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。//代码1
int arr1[10];
//代码2
int count = 10;
int arr2[count];//数组时候可以正常创建?
//代码3
char arr3[10];
float arr4[1];
double arr5[20];
#define _CRT_SECURE_NO_WARNINGS #include#include int main() { int arr[8]; char ch[5]; int arr1[10] = {1,2,3,4,5,6,7,8,9,10};//完全初始化 int arr2[10] = { 1,2,3,4,5 };//不完全初始化 int arr3[] = { 1,2,3,4,5 }; char ch1[5] = {'b', 'i', 't'};// char ch2[] = { 'b', 'i', 't' };//b i t char ch3[5] = "bit";//b i t 0 char ch4[] = "bit";//b i t printf("%dn", strlen(ch1));//3 printf("%dn", strlen(ch2));//随机值 printf("%dn", strlen(ch3));//3 printf("%dn", strlen(ch4));//3 printf("%sn", ch3);//bit printf("%sn", ch4);//bit return 0; }
- 数组的元素个数可以根据使用者明确指明,即arr,ch,arr1,arr2,ch1,ch3数组,
- 数组的元素个数可以根据初始化的内容来确定,即arr3,ch2,ch4数组,
- 数组可以不初始化,如果不初始化则默认补0,比如arr,ch数组,
- 数组可以完全初始化,也可以不完全初始化,完全初始化:arr1数组,不完全初始化:arr2,ch1,ch3数组,
- strlen这个库函数读取到结束,计算的是之间的字符长度,这里不细讲了,
#include总结 : 1. 数组是使用下标来访问的,下标是从 0 开始。 2. 数组的大小可以通过计算得到。int main () { int arr [ 10 ] = { 0 }; // 数组的不完全初始化 //计算数组的元素个数 int sz = sizeof ( arr ) / sizeof ( arr [ 0 ]); //对数组内容赋值 , 数组是使用下标来访问的,下标从 0 开始。所以: int i = 0 ; // 做下标 for ( i = 0 ; i < 10 ; i ++ ) // 这里写 10 ,好不好? { arr [ i ] = i ; } //输出数组的内容 for ( i = 0 ; i < 10 ; ++ i ) { printf ( "%d " , arr [ i ]); } return 0 ; }
int arr [ 10 ]; int sz = sizeof ( arr ) / sizeof ( arr [ 0 ]);一维数组在内存中的存储 接下来我们探讨数组在内存中的存储。 看代码:
#define _CRT_SECURE_NO_WARNINGS #includeint main() { int arr[10] = { 0 }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; ++i) { printf("&arr[%d] = %pn", i, &arr[i]); } return 0; }
- %p - 是按地址的格式打印 - 十六进制的打印
- 仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。 由此可以得出结论: 数组在内存中是连续存放的 。
// 数组创建 int arr [ 3 ][ 4 ]; char arr [ 3 ][ 5 ]; double arr [ 2 ][ 4 ];二维数组的初始化
// 数组初始化 int arr [ 3 ][ 4 ] = { 1 , 2 , 3 , 4 }; int arr [ 3 ][ 4 ] = {{ 1 , 2 },{ 4 , 5 }}; int arr [][ 4 ] = {{ 2 , 3 },{ 4 , 5 }}; // 二维数组如果有初始化,行可以省略,列不能省略二维数组的使用 二维数组的使用和一维数组使用一样,都是通过下标的方式进行访问 看代码:
#define _CRT_SECURE_NO_WARNINGS #include二维数组在内存中的存储 像一维数组一样,这里我们尝试打印二维数组的每个元素。int main() { //创建 int arr[3][4]; char ch[3][10]; //初始化 - 创建的同时给赋值 int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; int arr2[3][4] = { 1,2,3,4,5,6,7 };//不完全初始化 - 后面补0 int arr3[3][4] = { {1,2}, {3,4} ,{4,5} }; int arr4[][4] = { {1,2}, {3,4} ,{4,5} }; int i = 0; int j = 0; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) //1 2 0 0 { //3 4 0 0 printf("%d ", arr4[i][j]); //4 5 0 0 } printf("n"); } }
#define _CRT_SECURE_NO_WARNINGS #includeint main() { //二维数组在数组中存储 int arr[][4] = { {1,2}, {3,4} ,{4,5} }; int i = 0; int j = 0; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("&arr[%d][%d] = %pn", i, j, &arr[i][j]); } } }
- 通过结果我们可以分析到,其实二维数组在内存中也是连续存储的。
在进一步研究:
- 我们又发现,arr[0]可以看成一维数组的数组名,同理arr[1]和arr[2]也一样,
总结:二维数组在内存中是连续存放的,一行内部连续,跨行也是连续的,
三.数组越界 数组的下标是有范围限制的。 数组的下标规定是从 0 开始的,如果数组有 n 个元素,最后一个元素的下标就是 n-1 。 所以数组的下标如果小于 0 ,或者大于 n-1 ,就是数组越界访问了,超出了数组合法空间的访问。 C 语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的, 所以程序员写代码时,最好自己做越界的检查,#define _CRT_SECURE_NO_WARNINGS #includeint main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int i = 0; for (i = 0; i <= 10; i++) { printf("%d ", arr[i]);//当i等于10的时候,越界访问了 } return 0; }
- 虽然不报错,但是编译器会报警告, 进而更加确定数组是不能越界访问的,所以程序员写代码时,最好自己做越界的检查,
- 注:二维数组的行和列也可能存在越界。
- 其中如果要排10个数字则需要最多需要9趟冒泡排序,则n个数字最多需要n-1趟冒泡排序,因为原来的最后一个数字,已经到最前面的,所以少一次,
- 在一趟冒泡排序中如果有n个数字待排序,则需要n-1次比较,
代码如下:
#define _CRT_SECURE_NO_WARNINGS #includevoid bubble_sort(int arr[], int sz)//参数接收数组元素个数 { int i = 0; for (i = 0; i < sz - 1; i++) { int j = 0; for (j = 0; j < sz - i - 1; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } int main() { int arr[] = { 3,1,7,5,8,9,0,2,4,6 }; 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; }
- 其中不能把sz(求数组元素)定义在bubble_sort里面,数组传参传递的是数组首元素的地址,其实这也和sizeof这个库函数有关系,这里不详细的讲了
看代码:
#define _CRT_SECURE_NO_WARNINGS #includeint main() { int arr[10] = { 0 }; printf("%p ", &arr[0]);//1 printf("%p ", arr);//2-数组名是首元素的地址 printf("%p ", &arr);//3 - &arr取出的是数组的地址 printf("%p ", &arr + 1);//4 printf("%p ", arr);//5 printf("%p ", arr + 1);//6 int sz = sizeof(arr);//7 - 数组名表示整个数组 printf("%dn", sz); return 0; }
- 从第一个printf和第二个printf中可以看出数组名就是数组首元素的地址,
- 从第三个printf和第五个printf中可以看出取数组的地址和数组名的地址好像一样,但是从第3,第4,第5,第6个printf中发现取数组的地址+1和数组名的地址+1不一样,一个跳过40个地址,另一个跳过4个地址,所以得出结论取数组的地址和数组名的地址不一样
- 对于第三个printf来说,取的是数组地址,但是只是打印的数组首元素的地址,加1会跳过一个数组,
- 我在上面说了,数组名是首元素的地址,但是第7个printf它打印的不应该是数组首元素的地址吗?不应该是4吗?这不就和我说的矛盾了吗?其实只是一个特例,sizeof(数组名)计算的数组总的大小,所以结果是40,
总结:
1. sizeof( 数组名 ) ,计算整个数组的大小, sizeof 内部单独放一个数组名,数组名表示整个数 组。 2. & 数组名,取出的是数组的地址。 & 数组名,数组名表示整个数组。
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址。
数组实例 数组的应用实例 1 :三子棋 三子棋main.c 三子棋test.c 三子棋test.h 数组的应用实例2:扫雷 扫雷欢迎分享,转载请注明来源:内存溢出
评论列表(0条)