0.数组简介
数组是具有相同类型、有穷的、连续存储元素的集合。
例如:int arr[5] = {1, 2, 3, 4, 5} —— 数组arr里面都为int型(整型)数。
1.一维数组
1.1一维数组的创建和初始化
(1)一维数组创建
一般形式:数组类型 数组名[ 常量表达式 ]
例如:int arr[5]; ——这里指的是数组arr有5个元素arr[0]-arr[4](不存在arr[5]元素,数组下标都是从0开始的),元素类型都为整型
注意:a. [ ] 中应为常量表达式,不能使用变量
b. 常量表达式中应包含数字常量和符号常量
char arr1[5 + 3]; //这里含有数字常量3、5和符号常量+,为常量表达式,可编译通过
int count = 10;
int arr2[count]; //这里count为变量,所以编译不会通过,报错如下图
(2)一维数组的初始化
a.整型数组初始化
<1>.定义数组后必须要初始化,不要认为不初始化,系统就会自动初始化为0;如果不初始化,局部变量在栈上,各数组元素的值将是随机数;
<2>.初始化值的个数可少于数组元素个数.当初始化值的个数少于数组元素个数时,前面的按序初始化相应值, 后面的初始化为0;
<3>.当数组定义时没有指定大小,当初始化采用列表初始化了,那么数组的大小由初始化时列表元素个数决定。
int a[5] = { 1, 2, 3, 4, 5 };
print(a, 5); //这个print函数是我自己写的整型数组输出函数print(int arr[], int count)
// a[0]=1, a[1]=2, a[2]=3, a[3]=4, a[4]=5
int a1[5] = { 1, 2 }; //只对一部分元素赋值
print(a1, 5);
// a[0]=1, a[1]=2, a[2]=0, a[3]=0, a[4]=0
int a2[5] = { 0 }; //全部元素赋值为0;
print(a2, 5);
// a[0]=0, a[1]=0, a[2]=0, a[3]=0, a[4]=0
int a3[] = { 0, 1, 2, 3, 4 }; //知道元素个数,不指定数组长度
int len = sizeof(a3) / sizeof(a3[0]);
print(a3, len);
// a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4
b.字符串数组初始化
<1>char ch1[10] = {“hello”}; ——会自动将'\0'填充,此写法还可以省略掉{},写为:char ch1[10] = "hello";
<2>char ch2[10] = {'h', 'e', 'l', 'l', 'o', '\0'}; ——一个一个的初始化元素
注意:初始化字符数祖时,一定要给'\0'分配内存空间,虽然不会引起编译错误,但使用了不属于数组的空间,会有危险。
//char ch[]; //这个是错误的创建,如果后面写了元素,可不指定数组长度,但后面没有元素,则必须指定数组长度
char ch1[5] = { "hello" };
printf("%s\n", ch1);
char ch2[5] = "hello";
printf("%s\n", ch2);
char ch3[10] = { 'h', 'e', 'l', 'l', 'o', };
printf("%s\n", ch3);
//这里不要忘记为最后的,'\0'分配空间。如果要初始化一个字符串"hello",那为它定义的数组至少有6个数组元素,
//但是如果忘记了,一些编译器会自动补充
1.2一维数组的内存存储
数组在内存中是连续存在的。
1.3一维数组的使用
(1)数组形式访问
a.通过下标访问,下标从0开始。
[ ] 下标引用操作符,是数组访问的操作符。
b.数组的大小可通过计算得到。
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int len = sizeof(arr)/sizeof(arr[0]); //这里len计算为数组的大小
(2)指针形式访问
a.内存中一个内存单元(字节)对应一个地址。
b.在32位平台上指针的大小是4个字节,64位平台上指针的大小是8个字节。
指针是一个专门用来存放地址的变量,通过 解引用操作符(*)可以找到指针所指向的内容。
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%p\n", arr); //数组名代表首元素地址
printf("&arr[0] = %p\n", &arr[0]); //取出首元素地址
int *p = arr;
*p = 10;
printf("arr[2] = %p\n", &arr[2]);
printf("%p\n", arr + 2);
printf("%p\n", p + 2); //可以通过指针加下标找到对应的地址,再解引用就可以找到元素了
printf("arr[0] = %d\n", arr[0]);
printf("%d\n", *arr);
2.二维数组
2.1二维数组的创建和初始化
(1)二维数组创建
int arr1[3][4];
char arr2[5][6];
(2)二维数组初始化
a.不分行初始化:把{}中的元素依次赋给数组的各个元素
//数组创建及初始化
int arr1[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//二维数组的输出
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("arr[%d][%d]=%d ", i, j, arr1[i][j]);
}
printf("\n");
}
int arr2[3][4] = { { 1, 2, 3, 4 }, { 5, 6,7 }, { 8, 9, 10 } };
c.第一维定义省略时:系统可以根据第二维定义确定第一维长度
计算第一维定义的大小:初值个数能被第二维整除,所得到商就是第一维的大小;如果不能整除,则第一维大小的上再加1。
2.2二维数组的内存存储
二维数组存储,也是像一维数组一样在内存中是连续存储的。
int arr1[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//二维数组的输出
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("arr1[%d][%d]=%p\n", i, j, &arr1[i][j]);
}
}
即可认为,二维数组的首元素为arr1[0](第一行), 测试如下:
数组arr1在sizeof内部没有单独存在,且没有&,故arr1为首元素地址,首元素地址解引用,拿到首元素,计算可得为16个字节,刚好为第一行元素的大小。故,我们认为二维数组的首元素为第一行arr1[0]。