什么是数组
- 数组是一组相同类型元素的集合
一维数组的创建和初始化
元素类型 数组名[常量表达式]
常量表达式用来指定数组的大小
举个例子
int arr[5];
char ch[10];
同理float,double类型的数组只需要变更前面的元素类型即可
一维数组的初始化如下
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 1,2,3 };
int arr3[] = { 1,2,3,4 };
arr1为数组的完全初始化,arr2为数组的不完全初始化,剩余的元素默认为0,数组也可以像arr3一样初始化,这样数组的大小为大括号内元素的数量
char arr4[3] = { 'a',98, 'c' };
char arr5[] = { 'a','b','c' };
char arr6[] = "abc";
arr4和arr5是一样的,98是b的ASCII码值,arr5和arr6两种字符数组初始化的区别是arr6的后面会有一个'\0',arr5有三个元素,数组大小为三个字节,arr6有四个元素,数组大小为四个字节。
这让他们在使用strlen函数求字符串函数时会出现不同的结果,前者的返回值会是随机值,因为strlen计算的是'\0'之前的字符个数。
一维数组的使用
数组在初始化之后自然要去使用数组中的元素,就要使用[]操作符去访问数组中的元素,数组的下标第一个元素从0开始
for(int i=0; i<n; ++i)
{
printf("%d ", arr[i]);
}
这样就依次打印了数组中的元素
对以上函数稍作修改可以打印出数组中每个元素的地址
由此我们可以知道数组在内存中是连续存放的
二维数组的创建和初始化
二维数组的创建和一维数组类似
int arr[3][4];
char arr[3][5];
这样就可以创建出一个x行y列的数组
同样的二维数组的初始化和一维数组区别也不大
int a[2][2] = { 1,2,3,4 };
int b[2][2] = { {1,2},{3,4} };
如果像a数组这样初始化,大括号内的元素会被一次填入数组,在填满第一行后再填下一行
b数组大括号中的每一个大括号则是对二维数组的每一行进行初始化
二维数组的使用
同理可得二维数组的使用也是使用[] ,第一个[]访问二维数组的行,第二个[]访问二维数组的列,使用for循环的嵌套,i,j分别控制二维数组的行列就可以将这个二维数组打印出来
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
同理我们研究二维数组中每个元素的地址可以知道二维数组中的每一个元素之间物理上也是连续的,而不是单单每一行间的元素连续
二维数组的行列下标也是从0开始的
数组越界
数组从0开始,一个大小为N的数组,最后一个元素的下标是N-1,因此当数组的下标小于0,或者大于n-1,数组就越界访问了,超出了数组合法空间的访问。
数组名的含义
在用sizeof求数组大小时,数组名代表的是整个数组,在用&取数组地址时,取出的是数组的地址,此时的数组名代表的也是整个数组
但当数组名作为函数的参数时,此时的数组名是数组首元素的地址,所以如果在函数内部用sizeof求数组的大小,求出来的会是指针的大小
数组作为函数参数
因为数组作为函数参数时,传的是首元素的地址,因此在实现数组冒泡排序时也要传入数组的元素个数
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 - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}