1.一维数组
1.1一维数组的创建和初始化
数组是用于储存多个相同类型数据的集合。
数组的创建方式:
例如:int arr1 [10] ; int 就是它的类型,arr1就是它的名字,10就是它储存元素的个数。
数组创建的实例:
int arr1[5] = { 0 };
int arr2[5 + 6] = { 0 };
```这是常见的数组创建方式,={0},是将里面的元素全部初始化为0
上面提到【】中的为常量表达式,那【】中能不能放变量呢
int n = 10;
int arr[n] = { 0 };
很显然,在vs和IDE编译器中并不支持使用变量,编译器会告诉你必须使用常量。但其实在C99中,对这种变量数组有过规定,叫作变长数组,但上述两款编译器并不支持,所有就别为难编译器啦。ps:gcc支持
下面是一些更具体的初始化:
将每个元素都写出叫做完全初始化
int arr1[5] = { 1,2,3,4,5 };这是完全初始化的整形类型数组
char arr2[5] = { 'a','b','c','d','e' };这是完全初始化的字符类型数组
这是不完全初始化数组
int arr3[5] = { 1,2,3 };这是不完全初始化整形数组,但这里面有5个元素
char arr4[5]="abc";这是不完全初始化字符型数组
不足部分整形补整形0,字符类型字符0
根据后面元素个数来确定数组大小
int arr6[] = { 1,2,3 };这样也可以,这里面有3个元素
char arr7[]={'a','b','c'}在里面有3个元素,注意里面没有\0
char arr8[]="abc"这里面有4个元素,包含末尾的/0
后两种写法乍一看一样,但却有很大的区别,如果我们分别打印这两种数组结果会不同
这是因为%s要遇到/0才会停下,而第一个不含/0,那么编译器就会向后添加随机值,直到出现\0为止
1.2 一维数组的使用
1.数组是有下标的,下标从0开始
2.[ ]是下标访问操作符,用来访问下标
例如我创建一个数组:int arr[3]={1,2,3};
那么我们就可以通过下标来打印数组了
ps:目前打印整形数组只能通过下标来打印,不能像打印字符数组那样用%s直接打印(%s是打印字符串)
附带一个求字符串长度的公式:sizeof(arr)/sieof(arr[0]),例如上面的3就可以直接带这个算式算出来
1.3.一维数组在内存中的储存
这里我利用打印将数组内每个元素都打印出来
这里可以看出数组内每个元素的地址都是从低到高,且每个元素的地址都相差4,而一个整形就是4个字节,所以可以看出数组中每个元素是连续存放的。
1.一维数组在内存中是连续存放的
2.随着下表的增长,元素地址是由低到高变化的
所以编译器再访问数组时只需要知道第一个元素的地址,就可以推出后面元素的地址
2.二维数组
2.1二维数组的创建
这里[3][4]的意思是3行4列
2.2二维数组的初始化
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };挨个挨个初始化
int arr[3][4] = { 1,2,3,4,5 };不完全初始化,后面补0
int arr[3][4] = { {1,2},{5,6},{9,10} };
按行初始化补全应该是{1,2,0,0},{5,6,0,0},{9,10,0,0}
一维数组我们可以直接写为arr[ ],那么二维数组我们可不可以也这样写呢?答案是:行可以省,列不能省
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int arr[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
这两种写法是完全一致的,在没有行的情况下,编译器会根据你的列划分行。
如果出现这种情况:
int arr4[][2]={1,2,3,4,5,6,7,8,9};
它会自动补为5行且第5行补一个0
但注意列是万万不可省略的。
二维数组的打印其实跟一维数组类似,都是用下标打印,分别打印每个元素
这里i表示行,j表示列
2.3二维数组的储存
我们将二维数组的每个元素的地址都打印出来
从这里可以看出其实每个元素之间依然相差4个字节,二维数组在内存中其实跟一维数组是一样的,也是链式访问,元素之间也是像直线一样排列,并非我们所想的网格型
将二维数组想象成网格型能方便我们理解,但要记住它在内存中其实是连续的直线型。因此编译器在访问二维数组时,其实也像访问一维数组一样从前向后访问(从低地址到高地址)