知识点一:什么是数组
1)数组由一系列类型相同的数据对象依次排列组成;
a)依次排列:每个数组元素都是相邻的,从第一个数组元素到最后一个数组元素依次摆放。
b)类型相同:数组的元素都是类型相同的数据对象,不同的数据对象不能组成数组。
2)组成数组的数据对象被称作数组的元素;
知识点二:如何声明数组
1)我们可以用如下的代码,声明各种类型的单个变量
char c;
int n;
long l;
float f;
double df;
2)既然数组是由一系列类型相同的数据对象依次排列组成。那么声明数组至少要提供三类参数;
a)数组名;
b)数组元素的类型;
c)数组元素的数量;
3)数组声明的公式:元素类型 数组名 【元素数量】
4)数组的声明由数组名、元素类型、元素数量组成,例如:
char c[5];
int n[10];
long l[3];
float f[2];
double df[1];
知识点三:数组内容的初始化
1.初始化与赋值的区别
int n = 100; // 初始化为100
n = 100; // 赋值为100
1)第一行代码为声明int类型的变量n,并初始化为100。第二行代码为n赋值为100;
2)初始化与赋值的区别在于:
a)初始化时,等号的左边为变量的声明,等号的右边为值;
b)赋值时,等号的左边为变量,等号的右边为值;
c)初始化中的等号并不是赋值运算符,只是写作等号而已;
d)不能对一个变量多次初始化,会被认为变量被重复定义;
int n =100;
int n = 123; // 错误,会引发变量重定义
3)对一个变量重复赋值却没有问题;
int n;
n = 123;
n = 456;
2.数组的初始化
1)数组初始化如同基础数据类型初始化一样,也是在变量声明时加上等号,在等号右边写需要为数组初始 化的值;
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};
2)上面的代码能声明一个由 10 个 int 数据对象组成的数组,并且将它们分别初始化为1,2,3,4,5, 6,7,8,9,0;
3.初始化列表
1)数组初始化时,等号右边被称作初始化列表;
2)初始化列表写明数组的元素分别需要被初始化为何值,用逗号隔开,最后用花括号包括起来;
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};
@@上面这样将10个元素分别初始化为1,2,3,4,5,6,7,8,9,0
3)初始化列表短于数组长度:
int arr[10] = {1, 2 ,3 ,4 ,5};
@@现在数组有10个元素,而初始化列表只指定了5个元素的值。那么剩下的元素将被填0;
int arr[10] = {};
@@初始化列表什么都没有,所有数组元素将被填0;
4)初始化列表长于数组长度:
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 10, 11};
@@初始化列表长于数组长度,剩下的11将不知道初始化给哪个元素,代码将无法编译通过
5)让初始化列表决定数组长度:
int arr[] = {1726, 838, 938, 138, 58, 82, 83, 343, 456, 534, 645, 8938, 9382, 83, 343};
@@如果你有多个数值需要初始化给数组,但是你懒得数清楚到底有多少个。可以在数组声明的方括号里什 么都不填,这样将会让初始化列表决定数组的长度;
知识点四:访问数组的元素
1.访问数组元素的公式
1)访问数组指定元素的公式:数组名 [下标] #请特别注意,下标从0开始;
2.使用循环遍历数组元素
1)由于数组下标是递增的,使用 for 循环将更加便利地访问每一个元素;
for(int i = 0; i < 10; i++)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
}
2)在for循环中, i 将从0递增到9。使用 arr[i] ,即可访问下标从0到9的元素;
3)while循环也同样能做到,不过for循环代码将更加紧凑一些;
int i = 0;
while(i < 10)
{
printf("%d\n", arr[i++]); // 访问下标为i的元素
}
@@这里特别将 i++ 放入了函数调用当中。表达式 i++ 的结果为 i 当前的值,所以第一次求 i++ 的结果为 0。而后缀自增表达式会在稍后为 i 加1。这样写也能达到访问下标0到9的元素的效果;
4)i++ 写在单独的一行:
int i = 0;
while(i < 10)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
i++;
}
3.修改数组元素的值
int arr[10] = {}; // 所有元素均初始化为0
printf("%d\n", arr[5]); // 打印第6个元素的值
arr[5] = 123; // 将第6个元素赋值为123
printf("%d\n", arr[5]); // 打印第6个元素的值
1)使用赋值表达式:数组名[下标] = 表达式;可以为数组元素赋值为一个新值;
4.小心数组越界
1)如果数组只有10个元素,我们访问或修改了这10个元素以外的元素,那么结果是未定义的。这意味着程 序看上去可以运行,但是运行的结果很怪,或异常终止;
2)警告:千万不要越界访问或修改数组元素;
int arr[10] = {}; // 所有元素均初始化为0
printf("%d\n", arr[10]); // 下标为0到9,访问下标10的元素属于越界访问
3)如果使用循环来遍历数组,请特别注意循环条件;
for(int i = 0; i <= 10; i++)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
}
@@循环条件为 i <= 10 ,这意味着 i 可以为10。这样也将导致数组越界访问;
5.如果不初始化
#include <stdio.h>
int main()
{
int arr[10];
for(int i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
@@程序打印的结果均是一些奇怪的值,未初始化的数组里面都是一些无意义的数值;
##数组不一定要初始化,就像不初始化变量一样。如果不初始化变量,我们往往会在其后为其赋值。数组也是一样的,其后为其元素赋值,避免使用到无意义的数值;
#include <stdio.h>
int main()
{
int arr[10];
int n = 0;
for(int i = 0; i < 10; i++)
{
arr[i] = n;
n = n + 2;
}
for(int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
@@数组虽然未被初始化,但是其后,使用循环为每个元素赋值为从0开始的偶数;
知识点五:数组所占用的空间大小
char arr1[10];
short arr2[10];
int arr3[10];
long long arr4[10];
float arr5[10];
double arr6[10];
printf("%d\n", sizeof(arr1));
printf("%d\n", sizeof(arr2));
printf("%d\n", sizeof(arr3));
printf("%d\n", sizeof(arr4));
printf("%d\n", sizeof(arr5));
printf("%d\n", sizeof(arr6));
@@数组所占的空间 = 单个元素所占空间大小 * 数组元素个数;
sizeof(arr1) = sizeof(char) * 10 = 10
sizeof(arr2) = sizeof(short) * 10 = 20
sizeof(arr3) = sizeof(int) * 10 = 40
sizeof(arr4) = sizeof(long long) * 10 = 80
sizeof(arr5) = sizeof(float) * 10 = 40
sizeof(arr6) = sizeof(double) * 10 = 80
知识点六:数组能整体赋值吗?
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
arr1 = arr2;
¥¥¥:
1)第一个数组元素全部初始化为0,第二数组元素初始化为1,2,3,4,5;
2)如果使用赋值运算符让arr1赋值为arr2,是无法编译的;
3)如果重新初始化;
arr1 = {1, 2, 3, 4, 5};
@@这样也是不行的,初始化列表只能存在于初始化中;
##这里也是赋值与初始化区别的一个体现,在数组初始化中可以使用初始化列表,而赋值不行;
1.使用循环,单个为元素赋值
1)虽然无法整体为数组赋值,但是使用循环,单个为元素赋值却是可以的;
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
arr1[i] = arr2[i];
}
2.内存复制
1)另外,我们还可以借助 memcpy函数 (memory copy的简写),将arr2数组的数据复制到arr1数组;
#include <stdio.h>
#include <memory.h>
int main()
{
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
memcpy(arr1, arr2, sizeof(arr1));
for (int i = 0; i < 5; i++)
printf("%d ", arr1[i]);
return 0;
}
a)memcpy的第一个参数是目标数组名;
b)memcpy的第二个参数是原始数组名;
c)memcpy的第三个参数指明需要复制多少字节数据;
d)memcpy函数将会把arr2数组的数据复制到arr1数组,复制多少字节数据取决于第三个参数;
@@注意事项:设第三个参数,需要复制的字节数为N;
2) sizeof(arr2)不能小于N,否则复制完arr2的数据后,将复制到无意义内容;
3) sizeof(arr1)不能小于N,否则将没有足够空间存放数据;
4) 要使用memcpy函数,需要包含头文件 memory.h;
#include <stdio.h>
#include <memory.h>
int main()
{
int arr1[3] = {};
int arr2[5] = {1, 2, 3, 4, 5};
memcpy(arr1, arr2, sizeof(int) * 2);
for (int i = 0; i < 3; i++)
printf("%d ", arr1[i]);
return 0;
}
@@仅复制arr2中的sizeof(int) * 2字节数据到arr1。
@@即将arr2中前2个int元素的数据复制到arr1。
@@arr1可以容纳3个int,有足够的空间存放数据。