数组
数组是一组相同类型元素的集合。
可以通过数组的索引找到特定的元素,数组的索引从0开始
一维数组
一维数组的声明
数组声明的语法
type_t arr_name[const_n];
type_t 指数组的元素类型
arr_name 指数组的名字
const_n 是一个常量表达式,用来指定数组的大小
代码示例
int main()
{
//数组的声明
int arr1[8];
char arr2[9];
double arr3[10];
//数组创建,在C99标准之前,[] 中要给一个常量才可以,不能使用变量。
//在C99标准支持了变长数组的概念
int count = 8;
int arr[count];// 错误写法
return 0;
}
一维数组的初始化
数组的初始化指的是在数组声明时同时赋予数组合理的初始值
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
char arr2[5] = { 'a','b','c','d','e' };
//数组在声明的时候可不写元素的个数,但是不写元素个数就必须要初始化
//这时数组就会根据初始化的内容来确定数量
int arr3[] = { 1,2,3,4,5 };
char arr4[] = { 'a','b' };
return 0;
}
一维数组的使用
使用数组名[索引]
的方式可以访问数组的元素
int main()
{
//不完成初始化
//初始化元素的数量不足数组的长度,其余位置均补0
//相当于{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
int arr[10] = { 0 };
//通过遍历数组,给数组的每个元素赋值
//遍历是指逐个访问数组的元素
//遍历数组需要计算数组的长度
//通过arr[0]的方式访问索引为0的元素
int len = sizeof(arr) / sizeof(arr[0]);
//遍历数组,并赋值
int i = 0;
for (i = 0; i < len; i++)
{
arr[i] = i;
}
//遍历数组,查看数组每个元素的值
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果
0 1 2 3 4 5 6 7 8 9
一维数组在内存中的存储
下面的代码是查看数组每个元素的地址值
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int len = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < len; i++)
{
printf("arr[%d] = %p\n", i,&arr[i]);
}
return 0;
}
运行结果
arr[0] = 000000C82ED7FBF8
arr[1] = 000000C82ED7FBFC
arr[2] = 000000C82ED7FC00
arr[3] = 000000C82ED7FC04
arr[4] = 000000C82ED7FC08
arr[5] = 000000C82ED7FC0C
arr[6] = 000000C82ED7FC10
arr[7] = 000000C82ED7FC14
arr[8] = 000000C82ED7FC18
arr[9] = 000000C82ED7FC1C
总结:
数组在内存中是由低地址到高地址,连续存放的。
二维数组
二维数组的声明
int main()
{
int arr1[2][2];
char arr2[2][2];
double arr3[2][2];
return 0;
}
二维数组的初始化
int main()
{
int arr1[2][2] = { {1,2},{3,4} };
int arr2[2][2] = { 1,2,3,4 };//等同于上面
//不完全的初始化
int arr3[2][2] = { 1,2 };//等同{{1, 2}, {0, 0}}
//二维数组声明并初始化,可以省略行,但不能省略列
int arr4[][2] = { {1,2},{3,4} };
return 0;
}
二维数组的使用
int main()
{
int arr[2][3] = { 0 };
//遍历二维数组,并赋值
int i = 0;
for (i = 0; i < 2; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
arr[i][j] = i*3 + j;
}
}
//遍历二维数组,查看每个元素的值
for (i = 0; i < 2; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
二维数组在内存中的存储
int main()
{
int arr[2][3] = { {1,2,3}, {4,5,6} };
int i = 0;
for (i = 0; i < 2; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("arr[%d][%d] = %p\n", i, j, &arr[i][j]);
}
}
return 0;
}
运行结果:
arr[0][0] = 000000E6C84FF4F8
arr[0][1] = 000000E6C84FF4FC
arr[0][2] = 000000E6C84FF500
arr[1][0] = 000000E6C84FF504
arr[1][1] = 000000E6C84FF508
arr[1][2] = 000000E6C84FF50C
总结:
二维数组在内存中也是由低地址到高地址,连续存放的。
数组的越界
数组的索引范围使用限制的。
数组的索引是从0开始,如果数组的长度为n,那么最后一个元素的索引为n-1。
那么元素索引小于0,或大于n-1时,就是数组越界访问,超过了数组的空间。
C语言本身不做数组越界检查,编译器也不一定检查,都是编译器没有报错不代表程序没有问题。
所以,在访问数组元素时一定要注意数组越界问题。
代码示例
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <= 10; i++)
{
//当i等于10的时候,索引已经超过了最大使用,造成了越界访问
//但编译器没有报错,都是索引10的值并不是我们需要的值。
printf("%d ", arr[i]);
}
return 0;
}
数组作为函数参数
下面是一个打印数组元素的代码
void printf_arr(int arr[])
{
int i = 0;
int len = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < len;i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf_arr(arr);
return 0;
}
运行结果:
1 2
哦,结果不对,为啥?
通过调试发现我们求得的数组的长度不对,我们再看传过来的数组跟当做实参的数组不一样,函数里面的数组只有一个元素。
其实,数组名表示的是数组首元素的地址值,所求得的数组长度就不对,程序就没有达到我们需要的功能。
但是有两个例外
- sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
- &数组名,取出的是数组的地址。
打印数组元素的代码正确写法
void printf_arr(int arr[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//把数组长度计算写在函数外部
int len = sizeof(arr) / sizeof(arr[0]);
printf_arr(arr, len);
return 0;
}
本文出现任何错误,欢迎留言批评指正。