一.数组的创建
数组是一组相同类型元素的集合
格式
数组的类型 数组名 [ 数组的大小 ]
csint arr[20]; char arr[20];
注意:在VS编译器中数组的大小必须是常量
二.数组的初始化
cs
//这是个整形数组初始化
int arr[20] ={0}
//如果右边的值已经给了,那么方括号里面就不要写元素个数了
char ch1[]="abc"
char ch2[]={'a','b','c'}
1.这俩个方式区别
字符串中有\0,sizeof计算的时候把\0也计算进去了,所以是4
二.打印这俩种数组
cs
int main()
{
char ch1[] = "abc";
char ch2[] = { 'a','b','c' };
printf("%s\n", ch1);
printf("%s\n", ch2);
return 0;
}
代码运行
为什么呢
字符串后面有\0,\0是字符串结束的标志👇
而这个后面没有\0👇
所以这个打印时会继续往后访问,直到找到\0为止
在字符数组元素中写成数字,会转成ASCII值
三.一维数组在内存中存储
cs
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("arr[%d]=%p\n", i,&arr[i]);
}
return 0;
}
程序运行👇
由此可见,1.数组在内存中是连续存放的。
因为1个int是4个字节,arr[3]->arr[4]刚好是垮了4个字节
2.随着下标的增大,地址是由低到高变化的。
1.用地址来遍历数组中的地址
cs
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = &arr[0];
for (i = 0; i < sz; i++)
{
//因为数组在内存中是连续存放的,所以每次
//加1个整形,加4个字节,也就访问到了下一个数组的元素
printf("%p\n", p + i);
}
return 0;
}
程序运行👇
p+i与&arr[i]效果是一样的
2.对地址进行解引用从而遍历了数组
四.数组中有关地址的误区
1.数组名是数组首元素的地址
俩个例外
1.sizeof(数组名),数组名如果单独放在sizeof内部,这里的数组名表示整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
cs
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//数组名代表首元素的地址
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("%p\n", &arr[0]);
printf("%p\n", &arr[0] + 1);
//&arr,取出的是整个数组的地址
printf("%p\n", &arr);
printf("%p\n", &arr + 1);
return 0;
}
解释
五.二维数组
1.二维数组的创建
cs
int arr[3][4];
char arr[3][5];
double arr[3][4];
2.二维数组的初始化
cs
int arr[3][4] ={ 1,2,3,4 };
int arr[3][4] ={{1,2},{3,4}};
//行可以省略,列不能省略
//左边是行,右边是列
int arr[][4] ={{2,3},{4,5}};
理解如下
3.二维数组的访问
4.二维数组的遍历
%2d实现的是右对齐👇
%-2d实现的是左对齐👇
5.二维数组在内存中连续存储
二维数组在内存中是连续存放的
六.数组的越界
数组的下标是有范围限制的。 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。 C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,