前言:数组是一组相同元素的集合
一维数组
一、一维数组基础
(一)数组的创建
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
①数据类型 + 数组名 + [数组元素个数];
②数据类型 + 数组名 + [数组元素个数] = {0};
③数据类型 + 数组名 + [数组元素个数] = {内容};
④数据类型 + 数组名 + [ ] = {0};
⑤数据类型 + 数组名 + [ ] = {内容};
⑥char + 数组名 + [ ] = “内容”
⑦char + 数组名 + [ ] = {'字符',‘字符’,……}
注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数 组的概念,数组的大小可以使用变量指定,但是数组不能初始化。
(二)数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
- 指定值初始化
在数组创建时往往要在"[ ]"内输入数组元素个数来确定编译器划分多大的空间给该数组,而指定元素个数后空间后直接开始存储,便为数组的初始化。
即为(一)中②③④⑤这几种情况。
那么初始化具体怎么操作呢?
在完成“数据类型 + 数组名 + [数组元素个数]”部分后,在后面加上“ = {内容}”
”{ }“中的内容是存储在数组的元素,分别用逗号隔开,存储上限为前面设置的元素个数。
(值得注意的是char类型的字符串数组最后一位往往隐藏着'\0')
例:
int arr3[5] = {1,2,3,4,5};
char arr6[] = "abcdef";
char arr2[3] = {'a','b','c'};
2.非指定值初始化“[ ]”
数组在创建的时候如果想不指定数组的确定的大小就得初始化。
数组的元素个数根据初始化的内容来确 定。
例:
char arr6[] = "abcdef";
二、一维数组实操
(一)一维数组的使用
- 相关操作符
再此之前先介绍一个操作符: [] ,下标引用操作符。它其实就数组访问的操作符。
- 数组的访问
数组是使用下标来访问的,下标是从0开始。
数组名[元素下标] ; arr[4] = 5
int arr3[5] = {1,2,3,4,5};
元素 | 1 | 2 | 3 | 4 | 5 |
下标 | 0 | 1 | 2 | 3 | 4 |
访问 | arr[0] | arr[1] | arr[2] | arr[3] | arr[4] |
(二)数组的存储与计算
- 数组的存储
#include <stdio.h>
int main()
{
int arr[10] = {0};
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
for(i=0; i<sz; ++i)
{
printf("&arr[%d] = %p\n", i, &arr[i]);
}
return 0;
}
输入一串代码,打印出数组每个元素的地址
&arr[0] = 0000008102BEFA88
&arr[1] = 0000008102BEFA8C
&arr[2] = 0000008102BEFA90
&arr[3] = 0000008102BEFA94
&arr[4] = 0000008102BEFA98
&arr[5] = 0000008102BEFA9C
&arr[6] = 0000008102BEFAA0
&arr[7] = 0000008102BEFAA4
&arr[8] = 0000008102BEFAA8
&arr[9] = 0000008102BEFAAC
仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。 由此可以得出结论:数组在内存中是连续存放的。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
低地址————————————————————————————————➡高地址
通过这一层了解,我们就可以进行一些加减地址改变访问对象的操作。
int arr3[5] = {1,2,3,4,5};
inte* pa = &arr[3]
&a[3]+1=&a[4]
2.数组的计算
计算方法:
①sizeof()
②strlen()
③自定义函数
二维数组
一、二维数组基础
(一)二维数组的创建
格式和一维数组类似只不过[]变成了两个,也有一些别的要求
//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
(二)二维数组的初始化
左[]为行,右[]为列
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};//二维数组如果有初始化,行可以省略,列不能省略
注:二维数组如果有初始化,行可以省略,列不能省略
在只有一个大括号的格式下,元素按顺序分配下标
在有多个大括号的情况下,每个大括号代表一行
如int arr[3][4] = {{1,2},{4,5}};
1 | 2 | 0 | 0 |
4 | 5 | 0 | 0 |
0 | 0 | 0 | 0 |
注:为存元素默认为0('\0')
二、二维数组实操
(一)二维数组的使用
二维数组的使用也是通过下标的方式。
元素 | 1 | 2 | 0 | 0 |
下标 | [0][0] | [0][1] | [0][2] | [0][3] |
元素 | 4 | 5 | 0 | 0 |
下标 | [1][0] | [1][1] | [1][2] | [1][3] |
……
左【】对行,右【】对列
(二)二维数组的存储
像一维数组一样,这里我们尝试打印二维数组的每个元素。
#include <stdio.h>
int main()
{
int arr[3][4];
int i = 0;
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
}
}
return 0;
}
得到结果
&arr[0][0] = 000000FA1CCFFBB8
&arr[0][1] = 000000FA1CCFFBBC
&arr[0][2] = 000000FA1CCFFBC0
&arr[0][3] = 000000FA1CCFFBC4
&arr[1][0] = 000000FA1CCFFBC8
&arr[1][1] = 000000FA1CCFFBCC
&arr[1][2] = 000000FA1CCFFBD0
&arr[1][3] = 000000FA1CCFFBD4
&arr[2][0] = 000000FA1CCFFBD8
&arr[2][1] = 000000FA1CCFFBDC
&arr[2][2] = 000000FA1CCFFBE0
&arr[2][3] = 000000FA1CCFFBE4
通过结果我们可以分析到,其实二维数组在内存中也是连续存储的。 、创建一个简单二维数组:
int arr[4][2] = {1,2,3,4,5,6,7,8}
arr[0] | arr[1] | arr[2] | arr[3] | ||||
arr[0][0] | arr[0][1] | arr[1][0] | arr[1][1] | arr[2][0] | arr[2][1] | arr[3][0] | arr[3][1] |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
低地址————————————————————————————————➡高地址
数组相关知识
一、数组越界
数组的下标是有范围限制的。 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。 C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的, 所以程序员写代码时,最好自己做越界的检查。
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0; i<=10; i++)
{
printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
}
return 0;
}
结果为:1、2、3、4、5、6、7、8、9、10、-858993460
另:二维数组的行和列也可能存在越界
二、数组名是什么?
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
//输出结果
return 0;
}
得到结论,数组名是数组首元素地址
但也并非所有情况都适用
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数 组。 2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
int arr[10] = {0};
printf("%d\n", sizeof(arr));\\输出位40