数组,是一组相同类型元素的集合,其所有元素在内存中都是连续字节存放的,也就是说,数组保存在一大片连续的内存区中。
1. 数组定义及初始化
声明数组时,有三种方式:
- 明确的指出数组的元素个数,编译器会按照给定的元素个数来分配存储空间
- 不指定元素个数而直接进行初始化,编译器会根据你提供的初始化的个数来确定数组的元素个数
- 同时指定元素个数并且进行了初始化
但是不允许既不指定元素个数,又不初始化,因为编译器不知道到底该为数组分配多少存储空间。
一维数组:
int main()
{
//一维数组
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
int arr2[10] = { 1,2,3 }; //不完全初始化,剩余的元素默认都是0
int arr3[] = { 0 };//省略数组的大小,数组必须初始化,数组的大小是根据初始化的内容来确定的
char ch1[] = "abc"; //里有4个元素 :a,b,c,\0
char ch2[] = { 'a','b','c' }; //里有3个元素:a,b,c
char ch3[] = { 'a',98,'c' }; //这里的98是ASCII码值,表示的是b
return 0;
}
二维数组:
int main()
{
//二维数组
int arr1[4][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7},{4,5,6,7,8} };
int arr2[2][3] = { {1},{2,3} };
//二维数组即使初始化了,行可以省略,但列不能省略
int arr3[][3] = { 1,2,9,0 };
return 0;
}
数组实际上也是一个可以递归定义的概念:任何维数的数组都可以看作是由比它少一维的数组组成的一个一维数组。例如:int a[3][4][5]可以看作是由二维数组int b[4][5]组成的一维数组,其长度为3;而int b[4][5]又可以看作是由一维数组int c[5]组成的一个一维数组,其长度为4;c[5]则是int元素的数组,其长度为5.
2. 数组作为函数参数
数组名:通常情况下表示数组首元素的地址
但有两个例外:
- sizeof(数组名),这里的数组名表示的是整个数组 ,计算的是整个数组的大小,单位是字节
- &数组名,这里的数组名表示的也是整个数组,取出的是整个数组的地址。
所以,二维数组的数组名,表示的是首行元素的地址。
//数组作为函数参数
//冒泡排序:两两相邻的元素进行比较,n个元素进行n-1趟冒泡排序
void bubble_sort(int* arr,int sz)//这里的arr 本质上是指针变量
{
int i = 0;
//趟数
for (i = 0; i < sz-1; i++)
{
//一趟比较
int j = 0;
//每一趟开始前假设已经有序
int flag = 1;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 0;
}
}
if (flag == 1)
break;
}
}
int main()
{
int arr[10] = { 0 };
//输入
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
scanf("%d", &arr[i]);
}
//冒泡排序
//arr作为参数进行了传参,传递的是首元素的地址
bubble_sort(arr,sz); //升序
//打印
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3. 数组越界
数组的下标是有范围限制的,数组的下标规定是从0开始的,如果数组有n个元素,那么最后一个元素的下标就是n-1.
如果数组的下标小于0或者大于n-1,就称为数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查的,我们所使用的编译器也不一定会报错,但是编译器不报错,不意味着程序就是正确的。所以我们自己写代码的时候要做好越界的检查。