环境:CLion2021.3;64位macOS Big Sur
地表最强C语言系列传送门:
「地表最强」C语言(一)基本数据类型
「地表最强」C语言(二)变量和常量
「地表最强」C语言(三)字符串+转义字符+注释
「地表最强」C语言(四)分支语句
「地表最强」C语言(五)循环语句
「地表最强」C语言(六)函数
「地表最强」C语言(七)数组
「地表最强」C语言(八)操作符
「地表最强」C语言(九)关键字
「地表最强」C语言(十)#define定义常量和宏
「地表最强」C语言(十一)指针
「地表最强」C语言(十二)结构体、枚举和联合体
「地表最强」C语言(十三)动态内存管理,含柔性数组
「地表最强」C语言(十四)文件
「地表最强」C语言(十五)程序的环境和预处理
「地表最强」C语言(十六)一些自定义函数
「地表最强」C语言(十七)阅读程序
七、数组
1.数组:一组相同数据类型元素的集合。
2.初始化数组个数时,需要常量表达式而不能使用变量。(C99标准中可以使用,但是vs2019不支持)
3.
(1)数组类型:去掉数组名剩下的部分即为数组类型
(2)数组元素类型:去掉数字名和[],剩下的部分为数组中元素的类型
int arr[20];//数组类型为 int [20] 数组元素类型为int
4.数组名是数组首个元素的地址,是一个指针,因此若函数的形参需要地址,可以用数组接收也可以用指针接收。
注意,数组名为首元素的地址,但是有两个例外:
(1)sizeof(数组名):数组名表示的是整个数组,计算的是整个数组的大小,单位是字节。但是当数组名作为实参传递给一个数组时,sizeof(数组名)计算的是指针的大小而非数组的大小。
(2)&数组名取的是整个数组的地址,只不过在值上与数组首元素的地址相同。例如:
int arr[10] = { 0 };
printf("%p\n", &arr[0]);//很直观的首元素地址
printf("%p\n", arr);//数组名是首元素地址
printf("%p\n", arr + 1);//首元素地址+1,加的是是个元素的长度
printf("%p\n", &arr);//此处取出的是数组的地址,值和首元素的地址一样。
printf("%p\n", &arr + 1);//数组地址+1,加的是一个数组的长度。
7.1 一维数组
1.一维数组在内存中是连续存放的,随着数组下标的增长,地址是由低到高变化的。
int n = 8;
int arr[n];//不支持
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
int arr2[10] = { 1,2,3,4,5,6 };//不完全初始化,剩余元素默认为0
int arr3[] = { 1,2,3,4,5 };//根据初始化内容来确定个数--5
char ch1[7] = { 'h','e','l','l','o' };//未初始化的元素默认为\0 -- h e l l o \0 \0
char ch2[] = { 'h','e','l','l','o' };//h e l l o
char ch3[7] = "hello";//h e l l o \0 \0
char ch4[] = "hello";//h e l l o \0
printf("%s\n", ch1);
printf("%d\n", strlen(ch1));//求的是字符串的长度而不是数组
printf("%s\n", ch2);//遇到\0才停止,因此会出现乱码
printf("%d\n", strlen(ch2));//随机值,字符串长度与数组长度不一样
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;//数组名是首元素地址
for (int i = 0; i < 10; i++)
{
printf("%d ", *p);
p++;
}
7.2 二维数组
注意:初始化时可以省略行,但是不能省略列。
1.二维数组在内存中也是连续存放的,行内连续,行间也连续。实际上,二维数组在内存中也只有一行,只不过通过初始化时的列数来确定有几行,因此初始化时绝对不可以省略列。
2.如二维数组int arr[3][4],则:
(1)数组名为arr (2)二维数组的第一行的数组名为arr[0]
(3)二维数组的第二行的数组名为arr[1] (3)二维数组的第三行的数组名为arr[2]
理解:若要访问二维数组的第1行第2个元素可以通过arr[0][1]来实现,其中把前两部分看作一个整体即arr[0]和[1],就不难理解为什么arr[0]是第一行数组的数组名。
3.二维数组的首元素是第一行。
int arr[3][4];//创建3行4列的数组
int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int arr2[3][4] = { 1,2,3,4,5,6,7 };//不完全初始化,剩余元素补0
int arr3[3][4] = { {1,2},{3,4},{5,6} };//按行初始化
int arr4[][4] = { {1,2},{3,4},{5,6} };//初始化可以省略行,但是不能省略列
7.3 小练习:冒泡排序
void bubbleSort(int arr[],int length)
{
//确定需要多少趟
for(int i = 0;i < length - 1;i++)
{
//确定这一趟需要比较多少次
int flag = 1;//若本趟结束后没有改变这个标记,说明本躺已经有序,没有必要继续比下去
for(int j = 0;j < length - i - 1;j++)
{
if(arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;//说明本趟发生了交换,无法确定下一趟是否有序,因此需要继续比较。
}
}
if(flag == 1)
break;
}
}