(一)一维数组的创建和初始化
1.数组的创建
数组是一组相同类型元素的集合,
其创建方式为:type_t arr_name [const_n]
注:
type_t是数组类型
const_n是一个常量表达式,用来指定数组的大小
实例:
int arr1[10]
正确
int count=10;int arr2[count]
错误
2.数组的初始化
int arr1[10]={1,2,3};
不完全初始化,剩下的元素默认初始化为0
char arr2[5]={'a','b','c'};
为a,b,c,
char arr2[5]="abc"
亦可以初始化,为a,b,c,\0,
char arr4[]="abcdef";
为a,b,c,d,e,f,\0, 共七个
注:
#include<stdio.h>
#include<string.h>
int main()
{
char arr4[] = "abcdef";
printf("%d\n", sizeof(arr4));
printf("%d\n", strlen(arr4));
return 0;
}
sizeof是计算arr4所占空间大小
strlen是在求字符串长度(遇到\0停止,不计数\0;没遇到\0就随机大小)
strlen和sizeof无任何联系;
strlen是求字符串长度的;只针对字符串求长度;是库函数,要引用头文件;
sizeof是计算变量,数组,类型的大小;单位是字节;是操作符;
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abc";
char arr2[] = {'a','b','c'};
printf("%d\n", sizeof(arr1)); //4 a,b,c,\0
printf("%d\n", sizeof(arr2)); //3 a,b,c
printf("%d\n", strlen(arr1)); //3 a,b,c
printf("%d\n", strlen(arr2)); //随机数 a,b,c.....
return 0;
}
"abc"___a,a,c,\0字符型数组结尾有\0
{1,2,3,4}___1,2,3,4整形数组结尾无\0
3.一维数组的使用
对于数组的使用,之前我们了解了下标引用操作符[]。它其实就是数组访问的操作符。代码如下:
#include<stdio.h>
int main()
{
char arr[] = "abcdef";
int i = 0;
for (i = 0; i <= strlen(arr); i++)
printf("%c ", arr[i]);//arr数组名+[3]下标=这个数
return 0;
}
此时虽然可以运行,但因为strlen输出默认为无符号数,所以可以优化为:
(int)strlen(arr)>=i;
或int len=strlen(arr);len>=i;
总结
数组是可以通过使用下标来访问的,下标是从0开始;
数组的大小可以通过计算得到。
3.一维数组在内存中的存储
#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[i]是取i时的地址
return 0;
}
每个地址差4;元素是整形,占4个字节;
所以数组连续存放
(二)二维数组的创建和初始化
1.二维数组的创建
int arr[3][4]
表示三行四列
int int int int
int int int int
int int int int
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,5 };
return 0;
}
我们发现这样写会先用1 2 3 4把一行放满后,再用5放第二行
那怎么样才能现在第一行放1 2 3,就直接再第二行放4 5?
可以这样
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3},{4,5} };
return 0;
}
2.二维数组的初始化
int arr [][4]={1,2,3,4}
即使初始化,行可以省略,但是列不可以省略。
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3},{4,5} };
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;
}
#include<stdio.h>
int main()
{
int arr[3][4] = { {1,2,3},{4,5} };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("&arr[%d][%d]= %p\n", i, j, &arr[i][j]);
}
}
return 0;
}
我们可以看到不同行的地址仍是连续的。
(三)数组作为函数参数
在写代码的时候,会将数组作为参数传入函数,比如:我们要实现一个冒泡排序函数,将一个整型数组排序。
1.冒泡函数
错误编写 低效
int bubble_sort(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)//n个元素需要n-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;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz); //相当于传了&arr[0],直接改变主程序
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
我们发现无论数组是否已经排好序,程序都会将次数运行完;
正确编写
#include<stdio.h>
int bubble_sort(int arr[],int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)//n个元素需要n-1次排序
{
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;//break不用于选择,此时用于循环
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz); //此处arr传的是首元素的地址
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
2.数组名
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
return 0;
}
结论:数组名就是首元素地址;
两个例外:
sizeof(arr)
此时计算的时整个数组的大小
&arr
结果虽然相同,但取的是整个数组的地址
给arr加1后,可以发现,&arr多加了整个数组的字节
(四)数组越界
数组下标有范围限制,超过这个限制就会数组越界访问,此时编译器不一定报错,但不代表程序正确。