1.一维数组的创建和初始化
数组的创建
数组是一组相同数据类型元素的集合。
在创建数组时,我们必须定义数组的类型和大小,数组的大小不能为0。
type_t arr_name[const_n];
//type_t 是指数组的元素类型
//const_t 是一个常量表达式,用来指定数组的大小
int arr1[10];
char arr2[10];
float arr3[5];
double arr4[20];
数组的初始化
在创建数组的同时给数组的内容一些合理初始值(初始化)。
数组是聚合类型,整体赋值只有一次机会,在定义的同时。
int arr[]={};//数组定义之后,如果没有初始化,默认值为随机值。
int arr1[10] = {1, 2, 3};//如果局部初始化,其他数据默认值为0
int arr2[] = {1, 2, 3,4};//数组的大小为初始化数据的个数
int arr3[3] = {1, 2, 3, 4};//这是不可以的,不能超过数组长度
char arr4[]={'a','b','c'};//字符数组
char arr5[3] = {'a', 98, 'c'};//因为是字符类型,所以98其实就是字符'b'
char arr6[] = "abcdef";//
在内存中的存储
数组元素在内存中是从低地址到高地址并且连续存放的。
2.二维数组的创建和初始化
#include<stdio.h>
int main()
{
int arr1[3][4]={1,2,3,4};
int arr2[3][4]={{1,2},{4,5},{3,6}};
int arr3[][4]={1,2,3,4};//可以置为第0行
int arr4[3][]={1,2,3,4};//不可以删除列
return 0;
}
在内存中的存储
可以看出,同一维数组一样,二维数组在内存中也是从低地址到高地址连续存储的。
3.数组的使用
一维数组
int main()
{
int arr[10] = { 0 };//数组的不完全初始化
int len = sizeof(arr) / sizeof(arr[0]);//计算数组的元素个数
int i = 0;
for (i = 0; i < 10; i++)//i<11是不可以的,不可以越界访问
{
arr[i] = i;
}
for (i = 0; i < 10; ++i)
{
printf("%d ", arr[i]);//输出数组内容
}
return 0;
}
二维数组
int main()
{
int arr[3][4] = { 0 };//数组的不完全初始化
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
arr[i][j] = i * 4 + j;
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
一维数组和二维数组都是使用下标来访问的,下标是从0开始的。
数组的大小可以通过计算得到。(len=sizeof(arr) / sizeof(arr[0])
4.有关数组的运算
数组的传参,如果传数组名过来,那么就会退化为指针
数组名只有处于以下两种情况时才代表整个数组:
①sizeof(数组名) ②&数组名(如&a)数组名表示整个数组
#include<stdio.h>
int main()
{
//一维数组
int a[] = { 1, 2, 3, 4 };
printf("%d\n", sizeof(a));//16 数组名单独在sizeof内,表示整个数组,一个int型元素4个字节
printf("%d\n", sizeof(a + 0));//4 此处数组名不是单独在sizeof内,那表示的就是首元素地址,+0,那还是首元素地址,存地址的指针变量大小是四个字节。
printf("%d\n", sizeof(*a));//4 a是首元素地址,*a是首元素->1,int型占4个字节大小
printf("%d\n", sizeof(a + 1));//4 a是首元素地址,a+1是第二个元素的地址,它还是一个地址
printf("%d\n", sizeof(a[1]));//4 a[1]->第二个元素,整形数据4个字节
printf("%d\n", sizeof(&a));//4 &a虽然取出的是整个数组的地址,但它还是一个地址
printf("%d\n", sizeof(*&a));//16 &a取出的是整个数组的地址,对它进行解引用,就是这个数组,这个数字的大小就是16
printf("%d\n", sizeof(&a + 1));//4 &a取出的是整个数组的地址,加1跳过了整个数组(16个字节),但它还是一个地址
printf("%d\n", sizeof(&a[0]));//4 &a[0]取的是第一个元素的地址
printf("%d\n", sizeof(&a[0] + 1));//4 &a[0] + 1取的是第二个元素的地址
return 0;
}
#include<stdio.h>
//二维数组
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48 整个数组有12个元素,每个元素都是int型
printf("%d\n", sizeof(a[0][0]));//4 代表的是第一行第一列那个元素
printf("%d\n", sizeof(a[0]));//16 a[0]->第一行数组名,第一行总共有4个元素
printf("%d\n", sizeof(a[0] + 1));//4 a[0]降级变为a[0][0]的地址,a[0]+1是a[0][1]的地址
printf("%d\n", sizeof(a + 1));//4 a->首元素(第一行)地址,a+1->第二行地址
printf("%d\n", sizeof(&a[0] + 1));//4 第二行地址
printf("%d\n", sizeof(*a));//16 对第一行地址解引用就是第一行元素
printf("%d\n", sizeof(a[4]));//16 这里有好多人会出错,认为这个数组并没有这么大,只有3行,不能访问第4行,其实这里并没有访问第4行,它只是一个类型(1行的大小)
return 0;
}
5.数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传给函数。
eg:
void bubble(int arr[])
{
int sz = sizeof(arr)/sizeof(arr[0]);//这是错误的
...
}
数组作为函数参数时,不会把整个数组传递过去,实际上只是把数组的首元素地址传递过去了。