【C语言】 数组 目录1数组的概念2数组的创建和初始化3数组的使用4数组的内存存储情况5sizeof 计算数组的元素个数6二维数组7二维数组的初始化和创建8二维数组的使用9二维数值在内存的存储10C99中的变长数组1数组的概念数组是⼀组相同类型元素的集合从这个概念中我们就可以发现2个有价值的信息•数组中存放的是1个或者多个数据但是数组元素个数不能为0。•数组中存放的多个数据类型是相同的。数组分为⼀维数组和多维数组多维数组⼀般⽐较多⻅的是⼆维数组。2数组的创建和初始化1创建type arr_name[常量值];其实就类似声明变量一样不同之处就在于在后面加上一个[],在括号里面再加上常量。int arr [20];我们也可以使用其他的类型来声明数组。char str[20]; short ptr[10];str 是 char 类型 有20 个ptr 是 short 类型 有10个2初始化再声明数组时还需要使数组给一定的初始值这种就称位初始化。那给如何给数组初始化就需要用大括号把数据赋值对应的数组位置上。但我们也可以不需要全部初始因为如果有一个数值初始化了没有被初始化的数值会默认初始化为0.//完全初始化 int arr[10]{1,2,3,4,5,6,7,8,9,10}; //不完全初始化 int arr[10]{ 1 };//第一个元素初始化为1 全部默认为0 int arr[10]{ 0 };//第一个元素初始化为0 全部默认为0 int arr[3]{1,2,3,4}//error 初始化超出数值的范围3数组的使用1数组的下标int arr[10] {1,2,3,4,5,6,7,8,9,10}声明的数值不像我们想象的那样第一个数值的下标位置不是1而是0最后一个的下标不是10而是9所以我们声明出来的数值数组量为n最后一位的元素的下标是n-1。在C语⾔中数组的访问提供了⼀个操作符[] 这个操作符叫下标引⽤操作符。所以对应的 arr[0]1,arr[9]10;2数组元素输入与输出int main() { int arr[10]{0}; for(int i0;i10;i) { scanf(%d,arr[i]); } for(int i0;i10;i) { printf(%d,arr[i]); } return 0; }与声明的变量的使用方法是同一个道理学好如何去正确小标符“[]”就可以正确使用。4数组的内存存储情况该代码在x86 环境下的arr 内存情况一下#include stdio.h int main() { int i 0; int arr[10] {0}; for (i 0; i 10; i) { printf(arr[%d] %p\n, i, arr[i]); } printf( i %p, i); return 0; }如图所示从i 00EFF848到arr[9] 00EFF83C(这是以16进制)区间距离为12个字节位也就是3个int 的位置例外每一个arr数组的间距都是刚好4个字节位所以说数组的各个元素之间是连续的。为什么会故意去提一下在x86环境和i的地址呢int main() { int i 0; int arr[10] { 0 }; for (i 0; i 13; i) { arr[i] 0; printf(hehe\n); } return 0; }该代码是打印出多少个hehe答案是无限个而不是13个所以代码已经陷入死循环了。就是因为 从i 00EFF848到arr[9] 00EFF83C(这是以16进制)区间距离为12个字节位所以arr[12]和i的地址是同一个那么arr[12]和 i 也是控制同一个数值如果arr[12]0那么 i 也会等于0那么i13依然成立那么所以循环依然继续所以就陷入一个死循环当然这种情况只在x86环境但是在x64环境依然也是会发生的只是i 的值与arr[9]拉开的距离比较远而已。这个内容在《C缺陷与陷阱》的有详细讲述。5sizeof 计算数组的元素个数我们知道sizeof 可以用来计算声明类型的所占的字节大小那么他也可以用来计算arr 所占的字节大小并且也可以来计算出元素数量。int main() { int arr[10]; printf(%zu ,sizeof(arr)); printf(%zu ,sizeof(arr)/sizeof(arr[0])); return 0; }输出结果40 10一个sizeof 可以计算出arr 所占的内存长度那么两个sizeof计算后相除就可以计算出arr 的元素数量。6二维数组我们上面学的是一维数组那么一维数组和二维数组有什么区别呢其实区别并不大只是多了一个中括号“[]”int arr[3][5]; float str[4][2]; char a[3][4];7二维数组的初始化和创建初始化也是一样的依然需要大括号{}但是要明确哪里要初始化就需要两个大括号{}//不完全初始化 int arr1[3][5] {1, 2}; int arr2[3][5] {0}; //完全初始化 int arr3[3][5] {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7}; //按行初始化 int arr4[3][5] {{1,2},{3,4},{5,6}};初始化的行不能不能省略int arr5[][5] {1,2,3}; 1 int arr6[][5] {1,2,3,4,5,6,7}; int arr7[][5] {{1,2}, {3,4}, {5,6}};8二维数组的使用与一维数组同理第一行第一个都是arr[0][0]。#include stdio.h int main() { int arr[3][5] {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7}; printf(%d\n, arr[1][3]); return 0; }输出结果为5二维数组的输入与输出其实我们只要能够按照⼀定的规律产⽣所有的⾏和列的数字就⾏以上⼀段代码中的arr数组为例⾏的选择范围是0~2列的取值范围是0~4所以我们可以借助循环实现⽣成所有的下标。#include stdio.h int main() { int arr[3][5] {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7}; //输⼊ for(int i 0; i 3; i) //⾏号 { for(int j 0; j 5; j) //列号 { scanf(%d, arr[i][j]); //输⼊ } } //输出 for(int i 0; i 3; i) //⾏号 { for(int j 0; j 5; j) //列号 { printf(%d , arr[i][j]); //输出 } printf(\n); } return 0; }9二维数值在内存的存储代码展示#include stdio.h int main() { int arr[3][4] {0}; for (int i 0; i 3; i) { for (int j 0; j 4; j) { printf(arr[%d][%d] %p\n, i, j, arr[i][j]); } } return 0; }不难发现arr 各个元素的元素距离也依然都是相同的4个字节位注意int声明所以他们的内存空间也是一个有顺序的的排列int main() { int arr[3][4] { 0,1,2,3,1,2,3,4,2,3,4,5 }; for (int i 0; i 3; i) { for (int j 0; j 4; j) { printf(arr[%d][%d] %d\n, i, j, arr[i][j]); } } for (int i 0; i 12; i) printf(%d , arr[0][i]); return 0; }两种输出方式都是可以的。10C99中的变长数组通常在声明数组的时候是不可以在括号内添加变量的不然直接就报错了。但是有了C99种给了一个变长数组的特性允许我们可以自行更改数组的长度。在逻辑上 i 就可以随意更改arr 的数组元素数量编译器没法事先确定只有运⾏时才能知道 i是多少。#include stdio.h int main() { int n 0; scanf(%d, n);//根据输⼊数值确定数组的⼤⼩ int arr[n]; int i 0; for (i 0; i n; i) { scanf(%d, arr[i]); } for (i 0; i n; i) { printf(%d , arr[i]); } return 0; }第一次输出结果第二次输出结果感谢观看悠仁さん